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,378 @@
1
+ #include "cpu.h"
2
+ #include "common.h"
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #ifdef HAVE_ANDROID_GETCPUFEATURES
8
+ # include <cpu-features.h>
9
+ #endif
10
+ #ifdef __APPLE__
11
+ # include <mach/machine.h>
12
+ # include <sys/sysctl.h>
13
+ # include <sys/types.h>
14
+ #endif
15
+ #ifdef HAVE_SYS_AUXV_H
16
+ # include <sys/auxv.h>
17
+ #endif
18
+ #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
19
+ # include <intrin.h>
20
+ #endif
21
+
22
+ typedef struct CPUFeatures_ {
23
+ int initialized;
24
+ int has_neon;
25
+ int has_neon_aes;
26
+ int has_neon_sha3;
27
+ int has_sve2_aes;
28
+ int has_avx;
29
+ int has_avx2;
30
+ int has_avx512f;
31
+ int has_aesni;
32
+ int has_vaes;
33
+ int has_altivec;
34
+ } CPUFeatures;
35
+
36
+ static CPUFeatures _cpu_features;
37
+
38
+ #define CPUID_EBX_AVX2 0x00000020
39
+ #define CPUID_EBX_AVX512F 0x00010000
40
+
41
+ #define CPUID_ECX_AESNI 0x02000000
42
+ #define CPUID_ECX_XSAVE 0x04000000
43
+ #define CPUID_ECX_OSXSAVE 0x08000000
44
+ #define CPUID_ECX_AVX 0x10000000
45
+ #define CPUID_ECX_VAES 0x00000200
46
+
47
+ #define XCR0_SSE 0x00000002
48
+ #define XCR0_AVX 0x00000004
49
+ #define XCR0_OPMASK 0x00000020
50
+ #define XCR0_ZMM_HI256 0x00000040
51
+ #define XCR0_HI16_ZMM 0x00000080
52
+
53
+ // Define hwcap values ourselves: building with an old auxv header where these
54
+ // hwcap values are not defined should not prevent features from being enabled.
55
+
56
+ // Arm hwcaps.
57
+ #define AEGIS_ARM_HWCAP_NEON (1L << 12)
58
+ #define AEGIS_ARM_HWCAP2_AES (1L << 0)
59
+
60
+ // AArch64 hwcaps.
61
+ #define AEGIS_AARCH64_HWCAP_ASIMD (1L << 1)
62
+ #define AEGIS_AARCH64_HWCAP_AES (1L << 3)
63
+ #define AEGIS_AARCH64_HWCAP_SHA3 (1L << 17)
64
+ #define AEGIS_AARCH64_HWCAP2_SVEAES (1L << 2)
65
+
66
+ #if defined(__APPLE__) && defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64E)
67
+ // sysctlbyname() parameter documentation for instruction set characteristics:
68
+ // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
69
+ static inline int __attribute__((unused))
70
+ _have_arm_feature(const char *feature)
71
+ {
72
+ int64_t feature_present = 0;
73
+ size_t size = sizeof(feature_present);
74
+ if (sysctlbyname(feature, &feature_present, &size, NULL, 0) != 0) {
75
+ return 0;
76
+ }
77
+ return feature_present;
78
+ }
79
+
80
+ #elif (defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64)) && defined(AT_HWCAP)
81
+ static inline int
82
+ _have_hwcap(int hwcap_id, int bit)
83
+ {
84
+ unsigned long buf = 0;
85
+ # ifdef HAVE_GETAUXVAL
86
+ buf = getauxval(hwcap_id);
87
+ # elif defined(HAVE_ELF_AUX_INFO)
88
+ if (elf_aux_info(hwcap_id, (void *) &buf, (int) sizeof buf) != 0) {
89
+ return 0;
90
+ }
91
+ # endif
92
+ return (buf & bit) != 0;
93
+ }
94
+ #endif
95
+
96
+ static int
97
+ _runtime_arm_cpu_features(CPUFeatures *const cpu_features)
98
+ {
99
+ #ifndef __ARM_ARCH
100
+ return -1; /* LCOV_EXCL_LINE */
101
+ #endif
102
+
103
+ #if defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)
104
+ cpu_features->has_neon = 1;
105
+ #elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON)
106
+ cpu_features->has_neon = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0;
107
+ #elif (defined(__aarch64__) || defined(_M_ARM64)) && defined(AT_HWCAP)
108
+ cpu_features->has_neon = _have_hwcap(AT_HWCAP, AEGIS_AARCH64_HWCAP_ASIMD);
109
+ #elif defined(__arm__) && defined(AT_HWCAP)
110
+ cpu_features->has_neon = _have_hwcap(AT_HWCAP, AEGIS_ARM_HWCAP_NEON);
111
+ #endif
112
+
113
+ if (cpu_features->has_neon == 0) {
114
+ return 0;
115
+ }
116
+
117
+ #if __ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES
118
+ cpu_features->has_neon_aes = 1;
119
+ #elif defined(_M_ARM64)
120
+ // Assuming all CPUs supported by Arm Windows have the crypto extensions.
121
+ cpu_features->has_neon_aes = 1;
122
+ #elif defined(__APPLE__) && defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64E)
123
+ cpu_features->has_neon_aes = _have_arm_feature("hw.optional.arm.FEAT_AES");
124
+ #elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_AES)
125
+ cpu_features->has_neon_aes = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0x0;
126
+ #elif (defined(__aarch64__) || defined(_M_ARM64)) && defined(AT_HWCAP)
127
+ cpu_features->has_neon_aes = _have_hwcap(AT_HWCAP, AEGIS_AARCH64_HWCAP_AES);
128
+ #elif defined(__arm__) && defined(AT_HWCAP2)
129
+ cpu_features->has_neon_aes = _have_hwcap(AT_HWCAP2, AEGIS_ARM_HWCAP2_AES);
130
+ #endif
131
+
132
+ // The FEAT_SHA3 implementation assumes that FEAT_AES is also present.
133
+ if (cpu_features->has_neon_aes == 0) {
134
+ return 0;
135
+ }
136
+
137
+ // At the time of writing Windows does not provide a mechanism for
138
+ // detecting FEAT_SHA3, however FEAT_SHA3 is mandatory if FEAT_SVE_AES is
139
+ // also implemented, so test that instead.
140
+ #if __ARM_FEATURE_SHA3
141
+ cpu_features->has_neon_sha3 = 1;
142
+ #elif defined(_M_ARM64) && defined(PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE)
143
+ cpu_features->has_neon_sha3 = IsProcessorFeaturePresent(PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE);
144
+ #elif defined(__APPLE__) && defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64E)
145
+ cpu_features->has_neon_sha3 = _have_arm_feature("hw.optional.arm.FEAT_SHA3");
146
+ #elif (defined(__aarch64__) || defined(_M_ARM64)) && defined(AT_HWCAP)
147
+ cpu_features->has_neon_sha3 = _have_hwcap(AT_HWCAP, AEGIS_AARCH64_HWCAP_SHA3);
148
+ #endif
149
+
150
+ // The FEAT_SVE_AES implementation assumes that FEAT_AES and FEAT_SHA3 are
151
+ // also present.
152
+ if (cpu_features->has_neon_sha3 == 0) {
153
+ return 0;
154
+ }
155
+
156
+ // At the time of writing Apple Silicon platforms do not provide a
157
+ // mechanism for detecting FEAT_SVE_AES.
158
+ #if __ARM_FEATURE_SVE2_AES
159
+ cpu_features->has_sve2_aes = 1;
160
+ #elif defined(_M_ARM64) && defined(PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE)
161
+ cpu_features->has_sve2_aes = IsProcessorFeaturePresent(PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE);
162
+ #elif (defined(__aarch64__) || defined(_M_ARM64)) && defined(AT_HWCAP)
163
+ cpu_features->has_sve2_aes = _have_hwcap(AT_HWCAP2, AEGIS_AARCH64_HWCAP2_SVEAES);
164
+ #endif
165
+
166
+ return 0;
167
+ }
168
+
169
+ static void
170
+ _cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
171
+ {
172
+ #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) && \
173
+ !defined(__cpuid) /* __cpuid is a function on MSVC, can be an incompatible macro elsewhere */
174
+ __cpuid((int *) cpu_info, cpu_info_type);
175
+ #elif defined(HAVE_CPUID)
176
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
177
+ # ifdef __i386__
178
+ __asm__ __volatile__(
179
+ "pushfl; pushfl; "
180
+ "popl %0; "
181
+ "movl %0, %1; xorl %2, %0; "
182
+ "pushl %0; "
183
+ "popfl; pushfl; popl %0; popfl"
184
+ : "=&r"(cpu_info[0]), "=&r"(cpu_info[1])
185
+ : "i"(0x200000));
186
+ if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) {
187
+ return; /* LCOV_EXCL_LINE */
188
+ }
189
+ # endif
190
+ # ifdef __i386__
191
+ __asm__ __volatile__("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1"
192
+ : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]),
193
+ "=d"(cpu_info[3])
194
+ : "0"(cpu_info_type), "2"(0U));
195
+ # elif defined(__x86_64__)
196
+ __asm__ __volatile__("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1"
197
+ : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]),
198
+ "=d"(cpu_info[3])
199
+ : "0"(cpu_info_type), "2"(0U));
200
+ # else
201
+ __asm__ __volatile__("cpuid"
202
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
203
+ "=d"(cpu_info[3])
204
+ : "0"(cpu_info_type), "2"(0U));
205
+ # endif
206
+ #else
207
+ (void) cpu_info_type;
208
+ cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
209
+ #endif
210
+ }
211
+
212
+ static int
213
+ _runtime_intel_cpu_features(CPUFeatures *const cpu_features)
214
+ {
215
+ unsigned int cpu_info[4];
216
+ uint32_t xcr0 = 0U;
217
+
218
+ _cpuid(cpu_info, 0x0);
219
+ if (cpu_info[0] == 0U) {
220
+ return -1; /* LCOV_EXCL_LINE */
221
+ }
222
+ _cpuid(cpu_info, 0x00000001);
223
+
224
+ (void) xcr0;
225
+ #ifdef HAVE_AVXINTRIN_H
226
+ if ((cpu_info[2] & (CPUID_ECX_AVX | CPUID_ECX_XSAVE | CPUID_ECX_OSXSAVE)) ==
227
+ (CPUID_ECX_AVX | CPUID_ECX_XSAVE | CPUID_ECX_OSXSAVE)) {
228
+ xcr0 = 0U;
229
+ # if defined(HAVE__XGETBV) || \
230
+ (defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) && _MSC_FULL_VER >= 160040219)
231
+ xcr0 = (uint32_t) _xgetbv(0);
232
+ # elif defined(_MSC_VER) && defined(_M_IX86)
233
+ /*
234
+ * Visual Studio documentation states that eax/ecx/edx don't need to
235
+ * be preserved in inline assembly code. But that doesn't seem to
236
+ * always hold true on Visual Studio 2010.
237
+ */
238
+ __asm {
239
+ push eax
240
+ push ecx
241
+ push edx
242
+ xor ecx, ecx
243
+ _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
244
+ mov xcr0, eax
245
+ pop edx
246
+ pop ecx
247
+ pop eax
248
+ }
249
+ # elif defined(HAVE_AVX_ASM)
250
+ __asm__ __volatile__(".byte 0x0f, 0x01, 0xd0" /* XGETBV */
251
+ : "=a"(xcr0)
252
+ : "c"((uint32_t) 0U)
253
+ : "%edx");
254
+ # endif
255
+ if ((xcr0 & (XCR0_SSE | XCR0_AVX)) == (XCR0_SSE | XCR0_AVX)) {
256
+ cpu_features->has_avx = 1;
257
+ }
258
+ }
259
+ #endif
260
+
261
+ #ifdef HAVE_WMMINTRIN_H
262
+ cpu_features->has_aesni = ((cpu_info[2] & CPUID_ECX_AESNI) != 0x0);
263
+ #endif
264
+
265
+ #ifdef HAVE_AVX2INTRIN_H
266
+ if (cpu_features->has_avx) {
267
+ unsigned int cpu_info7[4];
268
+
269
+ _cpuid(cpu_info7, 0x00000007);
270
+ cpu_features->has_avx2 = ((cpu_info7[1] & CPUID_EBX_AVX2) != 0x0);
271
+ cpu_features->has_vaes =
272
+ cpu_features->has_aesni && ((cpu_info7[2] & CPUID_ECX_VAES) != 0x0);
273
+ }
274
+ #endif
275
+
276
+ cpu_features->has_avx512f = 0;
277
+ #ifdef HAVE_AVX512FINTRIN_H
278
+ if (cpu_features->has_avx2) {
279
+ unsigned int cpu_info7[4];
280
+
281
+ _cpuid(cpu_info7, 0x00000007);
282
+ /* LCOV_EXCL_START */
283
+ if ((cpu_info7[1] & CPUID_EBX_AVX512F) == CPUID_EBX_AVX512F &&
284
+ (xcr0 & (XCR0_OPMASK | XCR0_ZMM_HI256 | XCR0_HI16_ZMM)) ==
285
+ (XCR0_OPMASK | XCR0_ZMM_HI256 | XCR0_HI16_ZMM)) {
286
+ cpu_features->has_avx512f = 1;
287
+ }
288
+ /* LCOV_EXCL_STOP */
289
+ }
290
+ #endif
291
+
292
+ return 0;
293
+ }
294
+
295
+ static int
296
+ _runtime_powerpc_cpu_features(CPUFeatures *const cpu_features)
297
+ {
298
+ cpu_features->has_altivec = 0;
299
+ #if defined(__ALTIVEC__) && defined(__CRYPTO__)
300
+ cpu_features->has_altivec = 1;
301
+ #endif
302
+ return 0;
303
+ }
304
+
305
+ int
306
+ aegis_runtime_get_cpu_features(void)
307
+ {
308
+ int ret = -1;
309
+
310
+ memset(&_cpu_features, 0, sizeof _cpu_features);
311
+
312
+ ret &= _runtime_arm_cpu_features(&_cpu_features);
313
+ ret &= _runtime_intel_cpu_features(&_cpu_features);
314
+ ret &= _runtime_powerpc_cpu_features(&_cpu_features);
315
+ _cpu_features.initialized = 1;
316
+
317
+ return ret;
318
+ }
319
+
320
+ int
321
+ aegis_runtime_has_neon(void)
322
+ {
323
+ return _cpu_features.has_neon;
324
+ }
325
+
326
+ int
327
+ aegis_runtime_has_neon_aes(void)
328
+ {
329
+ return _cpu_features.has_neon_aes;
330
+ }
331
+
332
+ int
333
+ aegis_runtime_has_neon_sha3(void)
334
+ {
335
+ return _cpu_features.has_neon_sha3;
336
+ }
337
+
338
+ int
339
+ aegis_runtime_has_sve2_aes(void)
340
+ {
341
+ return _cpu_features.has_sve2_aes;
342
+ }
343
+
344
+ int
345
+ aegis_runtime_has_avx(void)
346
+ {
347
+ return _cpu_features.has_avx;
348
+ }
349
+
350
+ int
351
+ aegis_runtime_has_avx2(void)
352
+ {
353
+ return _cpu_features.has_avx2;
354
+ }
355
+
356
+ int
357
+ aegis_runtime_has_avx512f(void)
358
+ {
359
+ return _cpu_features.has_avx512f;
360
+ }
361
+
362
+ int
363
+ aegis_runtime_has_aesni(void)
364
+ {
365
+ return _cpu_features.has_aesni;
366
+ }
367
+
368
+ int
369
+ aegis_runtime_has_vaes(void)
370
+ {
371
+ return _cpu_features.has_vaes;
372
+ }
373
+
374
+ int
375
+ aegis_runtime_has_altivec(void)
376
+ {
377
+ return _cpu_features.has_altivec;
378
+ }
@@ -0,0 +1,34 @@
1
+ #ifndef cpu_H
2
+ #define cpu_H
3
+
4
+ #if defined(__ARM_FEATURE_CRYPTO) && defined(__ARM_FEATURE_AES) && defined(__ARM_NEON)
5
+ # define HAS_HW_AES
6
+ #elif defined(__AES__) && defined(__AVX__)
7
+ # define HAS_HW_AES
8
+ #elif defined(__ALTIVEC__) && defined(__CRYPTO__)
9
+ # define HAS_HW_AES
10
+ #endif
11
+
12
+ int aegis_runtime_get_cpu_features(void);
13
+
14
+ int aegis_runtime_has_neon(void);
15
+
16
+ int aegis_runtime_has_neon_aes(void);
17
+
18
+ int aegis_runtime_has_neon_sha3(void);
19
+
20
+ int aegis_runtime_has_sve2_aes(void);
21
+
22
+ int aegis_runtime_has_avx(void);
23
+
24
+ int aegis_runtime_has_avx2(void);
25
+
26
+ int aegis_runtime_has_avx512f(void);
27
+
28
+ int aegis_runtime_has_aesni(void);
29
+
30
+ int aegis_runtime_has_vaes(void);
31
+
32
+ int aegis_runtime_has_altivec(void);
33
+
34
+ #endif
@@ -0,0 +1,187 @@
1
+ #include "keccak.h"
2
+ #include "common.h"
3
+
4
+ #define KECCAK_ROUNDS 12
5
+
6
+ static inline uint64_t
7
+ ROTL64(uint64_t x, int b)
8
+ {
9
+ return (x << b) | (x >> (64 - b));
10
+ }
11
+
12
+ static const uint64_t RC[24] = {
13
+ 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
14
+ 0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
15
+ 0x000000000000008aULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
16
+ 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
17
+ 0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800aULL, 0x800000008000000aULL,
18
+ 0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL,
19
+ };
20
+
21
+ static void
22
+ keccakf(uint64_t st[25])
23
+ {
24
+ int round;
25
+ int i;
26
+ int j;
27
+ uint64_t t;
28
+ uint64_t bc[5];
29
+
30
+ for (round = 24 - KECCAK_ROUNDS; round < 24; round++) {
31
+ /* Theta */
32
+ for (i = 0; i < 5; i++) {
33
+ bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
34
+ }
35
+ for (i = 0; i < 5; i++) {
36
+ t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
37
+ for (j = 0; j < 25; j += 5) {
38
+ st[j + i] ^= t;
39
+ }
40
+ }
41
+
42
+ /* Rho Pi */
43
+ t = st[1];
44
+ {
45
+ static const int piln[24] = {
46
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
47
+ 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
48
+ };
49
+ static const int rotc[24] = {
50
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
51
+ 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
52
+ };
53
+ for (i = 0; i < 24; i++) {
54
+ j = piln[i];
55
+ bc[0] = st[j];
56
+ st[j] = ROTL64(t, rotc[i]);
57
+ t = bc[0];
58
+ }
59
+ }
60
+
61
+ /* Chi */
62
+ for (j = 0; j < 25; j += 5) {
63
+ for (i = 0; i < 5; i++) {
64
+ bc[i] = st[j + i];
65
+ }
66
+ for (i = 0; i < 5; i++) {
67
+ st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
68
+ }
69
+ }
70
+
71
+ /* Iota */
72
+ st[0] ^= RC[round];
73
+ }
74
+ }
75
+
76
+ static inline uint64_t
77
+ load64_le(const uint8_t src[8])
78
+ {
79
+ uint64_t w;
80
+ w = (uint64_t) src[0];
81
+ w |= (uint64_t) src[1] << 8;
82
+ w |= (uint64_t) src[2] << 16;
83
+ w |= (uint64_t) src[3] << 24;
84
+ w |= (uint64_t) src[4] << 32;
85
+ w |= (uint64_t) src[5] << 40;
86
+ w |= (uint64_t) src[6] << 48;
87
+ w |= (uint64_t) src[7] << 56;
88
+ return w;
89
+ }
90
+
91
+ static inline void
92
+ store64_le(uint8_t dst[8], uint64_t w)
93
+ {
94
+ dst[0] = (uint8_t) w;
95
+ w >>= 8;
96
+ dst[1] = (uint8_t) w;
97
+ w >>= 8;
98
+ dst[2] = (uint8_t) w;
99
+ w >>= 8;
100
+ dst[3] = (uint8_t) w;
101
+ w >>= 8;
102
+ dst[4] = (uint8_t) w;
103
+ w >>= 8;
104
+ dst[5] = (uint8_t) w;
105
+ w >>= 8;
106
+ dst[6] = (uint8_t) w;
107
+ w >>= 8;
108
+ dst[7] = (uint8_t) w;
109
+ }
110
+
111
+ static void
112
+ keccak_absorb_once(uint64_t st[25], size_t rate, const uint8_t *in, size_t inlen)
113
+ {
114
+ size_t i;
115
+
116
+ memset(st, 0, 25 * sizeof(uint64_t));
117
+ for (i = 0; i + 8 <= inlen; i += 8) {
118
+ st[i / 8] ^= load64_le(in + i);
119
+ }
120
+ if (i < inlen) {
121
+ uint8_t tail[8];
122
+ size_t rem = inlen - i;
123
+ memset(tail, 0, sizeof tail);
124
+ memcpy(tail, in + i, rem);
125
+ st[i / 8] ^= load64_le(tail);
126
+ }
127
+ st[inlen / 8] ^= (uint64_t) 0x1F << (8 * (inlen % 8));
128
+ st[(rate - 1) / 8] ^= (uint64_t) 0x80 << (8 * ((rate - 1) % 8));
129
+ keccakf(st);
130
+ }
131
+
132
+ static void
133
+ keccak_squeeze_once(uint8_t *out, size_t outlen, const uint64_t st[25])
134
+ {
135
+ size_t i;
136
+
137
+ for (i = 0; i + 8 <= outlen; i += 8) {
138
+ store64_le(out + i, st[i / 8]);
139
+ }
140
+ if (i < outlen) {
141
+ uint8_t tail[8];
142
+ store64_le(tail, st[i / 8]);
143
+ memcpy(out + i, tail, outlen - i);
144
+ }
145
+ }
146
+
147
+ void
148
+ aegis_kdf_128(uint8_t *out, size_t outlen, const uint8_t *context, size_t context_len,
149
+ const uint8_t *key, size_t key_len, const uint8_t *file_id, size_t file_id_len)
150
+ {
151
+ uint64_t st[25];
152
+ uint8_t buf[168];
153
+ size_t total = context_len + key_len + file_id_len;
154
+
155
+ if (total >= 168 || outlen > 168) {
156
+ memset(out, 0, outlen);
157
+ return;
158
+ }
159
+
160
+ memcpy(buf, context, context_len);
161
+ memcpy(buf + context_len, key, key_len);
162
+ memcpy(buf + context_len + key_len, file_id, file_id_len);
163
+
164
+ keccak_absorb_once(st, 168, buf, total);
165
+ keccak_squeeze_once(out, outlen, st);
166
+ }
167
+
168
+ void
169
+ aegis_kdf_256(uint8_t *out, size_t outlen, const uint8_t *context, size_t context_len,
170
+ const uint8_t *key, size_t key_len, const uint8_t *file_id, size_t file_id_len)
171
+ {
172
+ uint64_t st[25];
173
+ uint8_t buf[136];
174
+ size_t total = context_len + key_len + file_id_len;
175
+
176
+ if (total >= 136 || outlen > 136) {
177
+ memset(out, 0, outlen);
178
+ return;
179
+ }
180
+
181
+ memcpy(buf, context, context_len);
182
+ memcpy(buf + context_len, key, key_len);
183
+ memcpy(buf + context_len + key_len, file_id, file_id_len);
184
+
185
+ keccak_absorb_once(st, 136, buf, total);
186
+ keccak_squeeze_once(out, outlen, st);
187
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef keccak_H
2
+ #define keccak_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ void aegis_kdf_128(uint8_t *out, size_t outlen, const uint8_t *context, size_t context_len,
8
+ const uint8_t *key, size_t key_len, const uint8_t *file_id, size_t file_id_len);
9
+
10
+ void aegis_kdf_256(uint8_t *out, size_t outlen, const uint8_t *context, size_t context_len,
11
+ const uint8_t *key, size_t key_len, const uint8_t *file_id, size_t file_id_len);
12
+
13
+ #endif