pq_crypto 0.6.0 → 0.6.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/SECURITY.md +7 -0
- data/ext/pqcrypto/extconf.rb +2 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +139 -0
- data/ext/pqcrypto/pqcrypto_secure.c +532 -0
- data/ext/pqcrypto/pqcrypto_secure.h +20 -0
- data/ext/pqcrypto/pqcrypto_version.h +1 -1
- data/ext/pqcrypto/vendor/.vendored +4 -4
- data/ext/pqcrypto/vendor/mldsa-native/README.md +23 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/README.md +23 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +114 -58
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +498 -461
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +145 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +456 -422
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +47 -25
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +26 -14
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +56 -81
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +17 -24
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +33 -40
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +67 -87
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +19 -14
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +13 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +84 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +10 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +6 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +22 -15
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +376 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +204 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +259 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +1077 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +987 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +16 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +2 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +4 -2
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +2 -2
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +60 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +48 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +18 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +658 -582
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +5 -100
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +26 -25
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +334 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +355 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +8 -3
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/{xkcp.h → keccak_f1600_x4_avx2.h} +11 -8
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +44 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +454 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +37 -28
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +213 -196
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +248 -64
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt_aarch64_asm.S +753 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +129 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +145 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +177 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt_aarch64_asm.S +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery_aarch64_asm.S +84 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_aarch64_asm.S +53 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_aarch64_asm.S +55 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_aarch64_asm.S +86 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_aarch64_asm.S +86 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_aarch64_asm.S +103 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_aarch64_asm.S +111 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_aarch64_asm.S +75 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_aarch64_asm.S +72 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +23 -11
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_aarch64_asm.S +189 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_aarch64_asm.S +137 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_aarch64_asm.S +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +520 -516
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +34 -33
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +202 -242
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +25 -17
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +112 -28
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt_avx2_asm.S +2311 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt_avx2_asm.S +2383 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack_avx2_asm.S +238 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4_avx2_asm.S +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5_avx2_asm.S +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7_avx2_asm.S +187 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_avx2_asm.S +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2_asm.S +190 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +9 -8
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +10 -9
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +8 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +8 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +130 -129
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +109 -180
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +169 -150
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +56 -40
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +149 -164
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +52 -57
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +132 -167
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +57 -424
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +167 -474
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +308 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +22 -29
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +37 -43
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +511 -367
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +456 -417
- data/lib/pq_crypto/hybrid_kem.rb +1 -1
- data/lib/pq_crypto/internal.rb +23 -0
- data/lib/pq_crypto/kem.rb +27 -34
- data/lib/pq_crypto/pkcs8/der.rb +68 -0
- data/lib/pq_crypto/pkcs8/private_key_choice.rb +186 -0
- data/lib/pq_crypto/pkcs8.rb +51 -468
- data/lib/pq_crypto/serialization.rb +19 -29
- data/lib/pq_crypto/signature.rb +28 -35
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +10 -0
- data/script/vendor_libs.rb +3 -3
- metadata +44 -35
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +0 -376
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +0 -204
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +0 -259
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +0 -1077
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +0 -987
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +0 -488
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +0 -16
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +0 -753
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +0 -129
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +0 -145
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +0 -177
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +0 -653
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +0 -79
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +0 -53
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +0 -55
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +0 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +0 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +0 -102
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +0 -110
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +0 -72
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +0 -69
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +0 -189
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +0 -135
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +0 -128
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +0 -2311
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +0 -2383
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +0 -239
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +0 -131
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +0 -139
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +0 -155
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +0 -187
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +0 -61
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
#include <openssl/crypto.h>
|
|
16
16
|
#include <openssl/evp.h>
|
|
17
17
|
#include <openssl/rand.h>
|
|
18
|
+
#include <openssl/x509.h>
|
|
19
|
+
#include <openssl/pkcs12.h>
|
|
20
|
+
#include <openssl/objects.h>
|
|
18
21
|
|
|
19
22
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
20
23
|
#error "OpenSSL 3.0 or later is required for pq_crypto"
|
|
@@ -1159,6 +1162,535 @@ int pq_secret_key_from_pqc_container_pem(char **algorithm_out, uint8_t **key_out
|
|
|
1159
1162
|
return ret;
|
|
1160
1163
|
}
|
|
1161
1164
|
|
|
1165
|
+
#define PQ_PKCS8_PRIVATE_KEY_PEM_LABEL "PRIVATE KEY"
|
|
1166
|
+
#define PQ_PKCS8_ENCRYPTED_PRIVATE_KEY_PEM_LABEL "ENCRYPTED PRIVATE KEY"
|
|
1167
|
+
|
|
1168
|
+
static size_t pq_der_length_octets(size_t len) {
|
|
1169
|
+
size_t octets = 0;
|
|
1170
|
+
size_t v = len;
|
|
1171
|
+
|
|
1172
|
+
if (len < 0x80)
|
|
1173
|
+
return 1;
|
|
1174
|
+
do {
|
|
1175
|
+
octets++;
|
|
1176
|
+
v >>= 8;
|
|
1177
|
+
} while (v != 0);
|
|
1178
|
+
return 1 + octets;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
static int pq_der_write_length(uint8_t **cursor, size_t len) {
|
|
1182
|
+
uint8_t *p;
|
|
1183
|
+
size_t octets = 0;
|
|
1184
|
+
size_t v = len;
|
|
1185
|
+
|
|
1186
|
+
if (!cursor || !*cursor)
|
|
1187
|
+
return PQ_ERROR_BUFFER;
|
|
1188
|
+
|
|
1189
|
+
p = *cursor;
|
|
1190
|
+
if (len < 0x80) {
|
|
1191
|
+
*p++ = (uint8_t)len;
|
|
1192
|
+
*cursor = p;
|
|
1193
|
+
return PQ_SUCCESS;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
do {
|
|
1197
|
+
octets++;
|
|
1198
|
+
v >>= 8;
|
|
1199
|
+
} while (v != 0);
|
|
1200
|
+
if (octets > sizeof(size_t))
|
|
1201
|
+
return PQ_ERROR_BUFFER;
|
|
1202
|
+
|
|
1203
|
+
*p++ = (uint8_t)(0x80u | (uint8_t)octets);
|
|
1204
|
+
for (size_t i = 0; i < octets; ++i) {
|
|
1205
|
+
size_t shift = 8 * (octets - 1 - i);
|
|
1206
|
+
*p++ = (uint8_t)((len >> shift) & 0xffu);
|
|
1207
|
+
}
|
|
1208
|
+
*cursor = p;
|
|
1209
|
+
return PQ_SUCCESS;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
static int pq_der_read_length(const uint8_t *input, size_t input_len, size_t *offset,
|
|
1213
|
+
size_t *len_out) {
|
|
1214
|
+
uint8_t first;
|
|
1215
|
+
size_t len = 0;
|
|
1216
|
+
size_t length_octets;
|
|
1217
|
+
|
|
1218
|
+
if (!input || !offset || !len_out || *offset >= input_len)
|
|
1219
|
+
return PQ_ERROR_BUFFER;
|
|
1220
|
+
|
|
1221
|
+
first = input[(*offset)++];
|
|
1222
|
+
if (first < 0x80) {
|
|
1223
|
+
*len_out = (size_t)first;
|
|
1224
|
+
return PQ_SUCCESS;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
length_octets = (size_t)(first & 0x7fu);
|
|
1228
|
+
if (length_octets == 0 || length_octets > sizeof(size_t))
|
|
1229
|
+
return PQ_ERROR_BUFFER;
|
|
1230
|
+
if (input_len - *offset < length_octets)
|
|
1231
|
+
return PQ_ERROR_BUFFER;
|
|
1232
|
+
if (input[*offset] == 0)
|
|
1233
|
+
return PQ_ERROR_BUFFER;
|
|
1234
|
+
|
|
1235
|
+
for (size_t i = 0; i < length_octets; ++i) {
|
|
1236
|
+
if (len > (SIZE_MAX >> 8))
|
|
1237
|
+
return PQ_ERROR_BUFFER;
|
|
1238
|
+
len = (len << 8) | (size_t)input[*offset + i];
|
|
1239
|
+
}
|
|
1240
|
+
if (len < 0x80)
|
|
1241
|
+
return PQ_ERROR_BUFFER;
|
|
1242
|
+
|
|
1243
|
+
*offset += length_octets;
|
|
1244
|
+
*len_out = len;
|
|
1245
|
+
return PQ_SUCCESS;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
static int pq_der_expect_tlv(const uint8_t *input, size_t input_len, size_t *offset,
|
|
1249
|
+
uint8_t expected_tag, size_t *value_offset_out,
|
|
1250
|
+
size_t *value_len_out) {
|
|
1251
|
+
size_t value_len;
|
|
1252
|
+
size_t value_offset;
|
|
1253
|
+
|
|
1254
|
+
if (!input || !offset || !value_offset_out || !value_len_out || *offset >= input_len)
|
|
1255
|
+
return PQ_ERROR_BUFFER;
|
|
1256
|
+
if (input[(*offset)++] != expected_tag)
|
|
1257
|
+
return PQ_ERROR_BUFFER;
|
|
1258
|
+
if (pq_der_read_length(input, input_len, offset, &value_len) != PQ_SUCCESS)
|
|
1259
|
+
return PQ_ERROR_BUFFER;
|
|
1260
|
+
value_offset = *offset;
|
|
1261
|
+
if (input_len - value_offset < value_len)
|
|
1262
|
+
return PQ_ERROR_BUFFER;
|
|
1263
|
+
*offset = value_offset + value_len;
|
|
1264
|
+
*value_offset_out = value_offset;
|
|
1265
|
+
*value_len_out = value_len;
|
|
1266
|
+
return PQ_SUCCESS;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
static int pq_oid_text_to_der(const char *oid_text, uint8_t **oid_der_out,
|
|
1270
|
+
size_t *oid_der_len_out) {
|
|
1271
|
+
ASN1_OBJECT *obj = NULL;
|
|
1272
|
+
uint8_t *der = NULL;
|
|
1273
|
+
unsigned char *cursor;
|
|
1274
|
+
int der_len;
|
|
1275
|
+
int ret = PQ_ERROR_OPENSSL;
|
|
1276
|
+
|
|
1277
|
+
if (!oid_text || !oid_der_out || !oid_der_len_out)
|
|
1278
|
+
return PQ_ERROR_BUFFER;
|
|
1279
|
+
*oid_der_out = NULL;
|
|
1280
|
+
*oid_der_len_out = 0;
|
|
1281
|
+
|
|
1282
|
+
obj = OBJ_txt2obj(oid_text, 1);
|
|
1283
|
+
if (!obj)
|
|
1284
|
+
goto cleanup;
|
|
1285
|
+
der_len = i2d_ASN1_OBJECT(obj, NULL);
|
|
1286
|
+
if (der_len <= 0)
|
|
1287
|
+
goto cleanup;
|
|
1288
|
+
der = malloc((size_t)der_len);
|
|
1289
|
+
if (!der) {
|
|
1290
|
+
ret = PQ_ERROR_NOMEM;
|
|
1291
|
+
goto cleanup;
|
|
1292
|
+
}
|
|
1293
|
+
cursor = der;
|
|
1294
|
+
if (i2d_ASN1_OBJECT(obj, &cursor) != der_len || (size_t)(cursor - der) != (size_t)der_len)
|
|
1295
|
+
goto cleanup;
|
|
1296
|
+
|
|
1297
|
+
*oid_der_out = der;
|
|
1298
|
+
*oid_der_len_out = (size_t)der_len;
|
|
1299
|
+
der = NULL;
|
|
1300
|
+
ret = PQ_SUCCESS;
|
|
1301
|
+
|
|
1302
|
+
cleanup:
|
|
1303
|
+
if (der) {
|
|
1304
|
+
pq_secure_wipe(der, (size_t)(der_len > 0 ? der_len : 0));
|
|
1305
|
+
free(der);
|
|
1306
|
+
}
|
|
1307
|
+
if (obj)
|
|
1308
|
+
ASN1_OBJECT_free(obj);
|
|
1309
|
+
return ret;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
static int pq_oid_der_to_text(const uint8_t *oid_der, size_t oid_der_len, char **oid_text_out) {
|
|
1313
|
+
ASN1_OBJECT *obj = NULL;
|
|
1314
|
+
const unsigned char *cursor;
|
|
1315
|
+
char tmp[128];
|
|
1316
|
+
int text_len;
|
|
1317
|
+
char *copy = NULL;
|
|
1318
|
+
int ret = PQ_ERROR_OPENSSL;
|
|
1319
|
+
|
|
1320
|
+
if (!oid_der || oid_der_len == 0 || oid_der_len > (size_t)LONG_MAX || !oid_text_out)
|
|
1321
|
+
return PQ_ERROR_BUFFER;
|
|
1322
|
+
*oid_text_out = NULL;
|
|
1323
|
+
|
|
1324
|
+
cursor = oid_der;
|
|
1325
|
+
obj = d2i_ASN1_OBJECT(NULL, &cursor, (long)oid_der_len);
|
|
1326
|
+
if (!obj || cursor != oid_der + oid_der_len)
|
|
1327
|
+
goto cleanup;
|
|
1328
|
+
text_len = OBJ_obj2txt(tmp, sizeof(tmp), obj, 1);
|
|
1329
|
+
if (text_len <= 0 || (size_t)text_len >= sizeof(tmp))
|
|
1330
|
+
goto cleanup;
|
|
1331
|
+
copy = malloc((size_t)text_len + 1);
|
|
1332
|
+
if (!copy) {
|
|
1333
|
+
ret = PQ_ERROR_NOMEM;
|
|
1334
|
+
goto cleanup;
|
|
1335
|
+
}
|
|
1336
|
+
memcpy(copy, tmp, (size_t)text_len + 1);
|
|
1337
|
+
*oid_text_out = copy;
|
|
1338
|
+
copy = NULL;
|
|
1339
|
+
ret = PQ_SUCCESS;
|
|
1340
|
+
|
|
1341
|
+
cleanup:
|
|
1342
|
+
if (copy)
|
|
1343
|
+
free(copy);
|
|
1344
|
+
if (obj)
|
|
1345
|
+
ASN1_OBJECT_free(obj);
|
|
1346
|
+
return ret;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
int pq_pkcs8_private_key_info_to_der(uint8_t **output, size_t *output_len, const char *oid_text,
|
|
1350
|
+
const uint8_t *private_key, size_t private_key_len) {
|
|
1351
|
+
uint8_t *oid_der = NULL;
|
|
1352
|
+
size_t oid_der_len = 0;
|
|
1353
|
+
size_t alg_body_len, alg_len, priv_len, inner_len, total_len;
|
|
1354
|
+
uint8_t *buf = NULL;
|
|
1355
|
+
uint8_t *cur;
|
|
1356
|
+
int ret;
|
|
1357
|
+
|
|
1358
|
+
if (!output || !output_len || !oid_text || !private_key)
|
|
1359
|
+
return PQ_ERROR_BUFFER;
|
|
1360
|
+
*output = NULL;
|
|
1361
|
+
*output_len = 0;
|
|
1362
|
+
|
|
1363
|
+
ret = pq_oid_text_to_der(oid_text, &oid_der, &oid_der_len);
|
|
1364
|
+
if (ret != PQ_SUCCESS)
|
|
1365
|
+
return ret;
|
|
1366
|
+
|
|
1367
|
+
alg_body_len = oid_der_len;
|
|
1368
|
+
alg_len = 1 + pq_der_length_octets(alg_body_len) + alg_body_len;
|
|
1369
|
+
priv_len = 1 + pq_der_length_octets(private_key_len) + private_key_len;
|
|
1370
|
+
if (pq_size_add(3, alg_len, &inner_len) != PQ_SUCCESS ||
|
|
1371
|
+
pq_size_add(inner_len, priv_len, &inner_len) != PQ_SUCCESS) {
|
|
1372
|
+
ret = PQ_ERROR_BUFFER;
|
|
1373
|
+
goto cleanup;
|
|
1374
|
+
}
|
|
1375
|
+
if (pq_size_add(1 + pq_der_length_octets(inner_len), inner_len, &total_len) != PQ_SUCCESS) {
|
|
1376
|
+
ret = PQ_ERROR_BUFFER;
|
|
1377
|
+
goto cleanup;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
buf = malloc(total_len);
|
|
1381
|
+
if (!buf) {
|
|
1382
|
+
ret = PQ_ERROR_NOMEM;
|
|
1383
|
+
goto cleanup;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
cur = buf;
|
|
1387
|
+
*cur++ = 0x30;
|
|
1388
|
+
ret = pq_der_write_length(&cur, inner_len);
|
|
1389
|
+
if (ret != PQ_SUCCESS)
|
|
1390
|
+
goto cleanup;
|
|
1391
|
+
*cur++ = 0x02;
|
|
1392
|
+
*cur++ = 0x01;
|
|
1393
|
+
*cur++ = 0x00;
|
|
1394
|
+
*cur++ = 0x30;
|
|
1395
|
+
ret = pq_der_write_length(&cur, alg_body_len);
|
|
1396
|
+
if (ret != PQ_SUCCESS)
|
|
1397
|
+
goto cleanup;
|
|
1398
|
+
memcpy(cur, oid_der, oid_der_len);
|
|
1399
|
+
cur += oid_der_len;
|
|
1400
|
+
*cur++ = 0x04;
|
|
1401
|
+
ret = pq_der_write_length(&cur, private_key_len);
|
|
1402
|
+
if (ret != PQ_SUCCESS)
|
|
1403
|
+
goto cleanup;
|
|
1404
|
+
memcpy(cur, private_key, private_key_len);
|
|
1405
|
+
cur += private_key_len;
|
|
1406
|
+
if ((size_t)(cur - buf) != total_len) {
|
|
1407
|
+
ret = PQ_ERROR_BUFFER;
|
|
1408
|
+
goto cleanup;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
*output = buf;
|
|
1412
|
+
*output_len = total_len;
|
|
1413
|
+
buf = NULL;
|
|
1414
|
+
ret = PQ_SUCCESS;
|
|
1415
|
+
|
|
1416
|
+
cleanup:
|
|
1417
|
+
if (buf) {
|
|
1418
|
+
pq_secure_wipe(buf, total_len);
|
|
1419
|
+
free(buf);
|
|
1420
|
+
}
|
|
1421
|
+
if (oid_der) {
|
|
1422
|
+
pq_secure_wipe(oid_der, oid_der_len);
|
|
1423
|
+
free(oid_der);
|
|
1424
|
+
}
|
|
1425
|
+
return ret;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
int pq_pkcs8_private_key_info_from_der(char **oid_text_out, uint8_t **private_key_out,
|
|
1429
|
+
size_t *private_key_len_out, const uint8_t *input,
|
|
1430
|
+
size_t input_len) {
|
|
1431
|
+
size_t offset = 0;
|
|
1432
|
+
size_t outer_off = 0, outer_len = 0, outer_end;
|
|
1433
|
+
size_t alg_off = 0, alg_len = 0, alg_end;
|
|
1434
|
+
size_t oid_off = 0, oid_len = 0;
|
|
1435
|
+
size_t priv_off = 0, priv_len = 0;
|
|
1436
|
+
uint8_t *private_key = NULL;
|
|
1437
|
+
char *oid_text = NULL;
|
|
1438
|
+
int ret;
|
|
1439
|
+
|
|
1440
|
+
if (!oid_text_out || !private_key_out || !private_key_len_out || !input)
|
|
1441
|
+
return PQ_ERROR_BUFFER;
|
|
1442
|
+
*oid_text_out = NULL;
|
|
1443
|
+
*private_key_out = NULL;
|
|
1444
|
+
*private_key_len_out = 0;
|
|
1445
|
+
|
|
1446
|
+
ret = pq_der_expect_tlv(input, input_len, &offset, 0x30, &outer_off, &outer_len);
|
|
1447
|
+
if (ret != PQ_SUCCESS)
|
|
1448
|
+
return ret;
|
|
1449
|
+
outer_end = outer_off + outer_len;
|
|
1450
|
+
if (offset != input_len || outer_end != input_len)
|
|
1451
|
+
return PQ_ERROR_BUFFER;
|
|
1452
|
+
|
|
1453
|
+
offset = outer_off;
|
|
1454
|
+
{
|
|
1455
|
+
size_t version_off = 0, version_len = 0;
|
|
1456
|
+
ret = pq_der_expect_tlv(input, outer_end, &offset, 0x02, &version_off, &version_len);
|
|
1457
|
+
if (ret != PQ_SUCCESS)
|
|
1458
|
+
return ret;
|
|
1459
|
+
if (version_len != 1 || input[version_off] != 0x00)
|
|
1460
|
+
return PQ_ERROR_BUFFER;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
ret = pq_der_expect_tlv(input, outer_end, &offset, 0x30, &alg_off, &alg_len);
|
|
1464
|
+
if (ret != PQ_SUCCESS)
|
|
1465
|
+
return ret;
|
|
1466
|
+
alg_end = alg_off + alg_len;
|
|
1467
|
+
{
|
|
1468
|
+
size_t alg_cursor = alg_off;
|
|
1469
|
+
size_t oid_tlv_start = alg_cursor;
|
|
1470
|
+
ret = pq_der_expect_tlv(input, alg_end, &alg_cursor, 0x06, &oid_off, &oid_len);
|
|
1471
|
+
if (ret != PQ_SUCCESS)
|
|
1472
|
+
return ret;
|
|
1473
|
+
if (alg_cursor != alg_end)
|
|
1474
|
+
return PQ_ERROR_BUFFER;
|
|
1475
|
+
ret = pq_oid_der_to_text(input + oid_tlv_start, alg_cursor - oid_tlv_start, &oid_text);
|
|
1476
|
+
}
|
|
1477
|
+
if (ret != PQ_SUCCESS)
|
|
1478
|
+
return ret;
|
|
1479
|
+
|
|
1480
|
+
ret = pq_der_expect_tlv(input, outer_end, &offset, 0x04, &priv_off, &priv_len);
|
|
1481
|
+
if (ret != PQ_SUCCESS)
|
|
1482
|
+
goto cleanup;
|
|
1483
|
+
if (offset != outer_end) {
|
|
1484
|
+
ret = PQ_ERROR_BUFFER;
|
|
1485
|
+
goto cleanup;
|
|
1486
|
+
}
|
|
1487
|
+
private_key = malloc(priv_len ? priv_len : 1);
|
|
1488
|
+
if (!private_key) {
|
|
1489
|
+
ret = PQ_ERROR_NOMEM;
|
|
1490
|
+
goto cleanup;
|
|
1491
|
+
}
|
|
1492
|
+
if (priv_len)
|
|
1493
|
+
memcpy(private_key, input + priv_off, priv_len);
|
|
1494
|
+
|
|
1495
|
+
*oid_text_out = oid_text;
|
|
1496
|
+
*private_key_out = private_key;
|
|
1497
|
+
*private_key_len_out = priv_len;
|
|
1498
|
+
oid_text = NULL;
|
|
1499
|
+
private_key = NULL;
|
|
1500
|
+
ret = PQ_SUCCESS;
|
|
1501
|
+
|
|
1502
|
+
cleanup:
|
|
1503
|
+
if (oid_text)
|
|
1504
|
+
free(oid_text);
|
|
1505
|
+
if (private_key) {
|
|
1506
|
+
pq_secure_wipe(private_key, priv_len);
|
|
1507
|
+
free(private_key);
|
|
1508
|
+
}
|
|
1509
|
+
return ret;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
int pq_pkcs8_encrypt_private_key_info_der(uint8_t **output, size_t *output_len,
|
|
1513
|
+
const uint8_t *plain_der, size_t plain_der_len,
|
|
1514
|
+
const char *passphrase, size_t passphrase_len,
|
|
1515
|
+
int iterations) {
|
|
1516
|
+
const unsigned char *cursor;
|
|
1517
|
+
PKCS8_PRIV_KEY_INFO *p8 = NULL;
|
|
1518
|
+
X509_SIG *encrypted = NULL;
|
|
1519
|
+
unsigned char salt[16];
|
|
1520
|
+
unsigned char *der = NULL;
|
|
1521
|
+
unsigned char *der_cursor;
|
|
1522
|
+
int der_len;
|
|
1523
|
+
int ret = PQ_ERROR_OPENSSL;
|
|
1524
|
+
|
|
1525
|
+
if (!output || !output_len || !plain_der || !passphrase || iterations <= 0 ||
|
|
1526
|
+
passphrase_len > (size_t)INT_MAX || plain_der_len > (size_t)LONG_MAX)
|
|
1527
|
+
return PQ_ERROR_BUFFER;
|
|
1528
|
+
*output = NULL;
|
|
1529
|
+
*output_len = 0;
|
|
1530
|
+
|
|
1531
|
+
cursor = plain_der;
|
|
1532
|
+
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &cursor, (long)plain_der_len);
|
|
1533
|
+
if (!p8 || cursor != plain_der + plain_der_len)
|
|
1534
|
+
goto cleanup;
|
|
1535
|
+
if (RAND_bytes(salt, sizeof(salt)) != 1)
|
|
1536
|
+
goto cleanup;
|
|
1537
|
+
|
|
1538
|
+
encrypted = PKCS8_encrypt(-1, EVP_aes_256_cbc(), passphrase, (int)passphrase_len, salt,
|
|
1539
|
+
(int)sizeof(salt), iterations, p8);
|
|
1540
|
+
if (!encrypted)
|
|
1541
|
+
goto cleanup;
|
|
1542
|
+
|
|
1543
|
+
der_len = i2d_X509_SIG(encrypted, NULL);
|
|
1544
|
+
if (der_len <= 0) {
|
|
1545
|
+
ret = PQ_ERROR_OPENSSL;
|
|
1546
|
+
goto cleanup;
|
|
1547
|
+
}
|
|
1548
|
+
der = malloc((size_t)der_len);
|
|
1549
|
+
if (!der) {
|
|
1550
|
+
ret = PQ_ERROR_NOMEM;
|
|
1551
|
+
goto cleanup;
|
|
1552
|
+
}
|
|
1553
|
+
der_cursor = der;
|
|
1554
|
+
if (i2d_X509_SIG(encrypted, &der_cursor) != der_len ||
|
|
1555
|
+
(size_t)(der_cursor - der) != (size_t)der_len)
|
|
1556
|
+
goto cleanup;
|
|
1557
|
+
|
|
1558
|
+
*output = der;
|
|
1559
|
+
*output_len = (size_t)der_len;
|
|
1560
|
+
der = NULL;
|
|
1561
|
+
ret = PQ_SUCCESS;
|
|
1562
|
+
|
|
1563
|
+
cleanup:
|
|
1564
|
+
pq_secure_wipe(salt, sizeof(salt));
|
|
1565
|
+
if (der) {
|
|
1566
|
+
pq_secure_wipe(der, (size_t)(der_len > 0 ? der_len : 0));
|
|
1567
|
+
free(der);
|
|
1568
|
+
}
|
|
1569
|
+
if (encrypted)
|
|
1570
|
+
X509_SIG_free(encrypted);
|
|
1571
|
+
if (p8)
|
|
1572
|
+
PKCS8_PRIV_KEY_INFO_free(p8);
|
|
1573
|
+
return ret;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
int pq_pkcs8_decrypt_private_key_info_der(uint8_t **output, size_t *output_len,
|
|
1577
|
+
const uint8_t *encrypted_der, size_t encrypted_der_len,
|
|
1578
|
+
const char *passphrase, size_t passphrase_len) {
|
|
1579
|
+
const unsigned char *cursor;
|
|
1580
|
+
X509_SIG *encrypted = NULL;
|
|
1581
|
+
PKCS8_PRIV_KEY_INFO *p8 = NULL;
|
|
1582
|
+
unsigned char *der = NULL;
|
|
1583
|
+
unsigned char *der_cursor;
|
|
1584
|
+
int der_len;
|
|
1585
|
+
int ret = PQ_ERROR_OPENSSL;
|
|
1586
|
+
|
|
1587
|
+
if (!output || !output_len || !encrypted_der || !passphrase ||
|
|
1588
|
+
passphrase_len > (size_t)INT_MAX || encrypted_der_len > (size_t)LONG_MAX)
|
|
1589
|
+
return PQ_ERROR_BUFFER;
|
|
1590
|
+
*output = NULL;
|
|
1591
|
+
*output_len = 0;
|
|
1592
|
+
|
|
1593
|
+
cursor = encrypted_der;
|
|
1594
|
+
encrypted = d2i_X509_SIG(NULL, &cursor, (long)encrypted_der_len);
|
|
1595
|
+
if (!encrypted || cursor != encrypted_der + encrypted_der_len)
|
|
1596
|
+
goto cleanup;
|
|
1597
|
+
p8 = PKCS8_decrypt(encrypted, passphrase, (int)passphrase_len);
|
|
1598
|
+
if (!p8)
|
|
1599
|
+
goto cleanup;
|
|
1600
|
+
|
|
1601
|
+
der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL);
|
|
1602
|
+
if (der_len <= 0)
|
|
1603
|
+
goto cleanup;
|
|
1604
|
+
der = malloc((size_t)der_len);
|
|
1605
|
+
if (!der) {
|
|
1606
|
+
ret = PQ_ERROR_NOMEM;
|
|
1607
|
+
goto cleanup;
|
|
1608
|
+
}
|
|
1609
|
+
der_cursor = der;
|
|
1610
|
+
if (i2d_PKCS8_PRIV_KEY_INFO(p8, &der_cursor) != der_len ||
|
|
1611
|
+
(size_t)(der_cursor - der) != (size_t)der_len)
|
|
1612
|
+
goto cleanup;
|
|
1613
|
+
|
|
1614
|
+
*output = der;
|
|
1615
|
+
*output_len = (size_t)der_len;
|
|
1616
|
+
der = NULL;
|
|
1617
|
+
ret = PQ_SUCCESS;
|
|
1618
|
+
|
|
1619
|
+
cleanup:
|
|
1620
|
+
if (der) {
|
|
1621
|
+
pq_secure_wipe(der, (size_t)(der_len > 0 ? der_len : 0));
|
|
1622
|
+
free(der);
|
|
1623
|
+
}
|
|
1624
|
+
if (p8)
|
|
1625
|
+
PKCS8_PRIV_KEY_INFO_free(p8);
|
|
1626
|
+
if (encrypted)
|
|
1627
|
+
X509_SIG_free(encrypted);
|
|
1628
|
+
return ret;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
int pq_pkcs8_der_is_encrypted_private_key_info(const uint8_t *input, size_t input_len) {
|
|
1632
|
+
const unsigned char *cursor;
|
|
1633
|
+
X509_SIG *encrypted = NULL;
|
|
1634
|
+
const X509_ALGOR *alg = NULL;
|
|
1635
|
+
const ASN1_OCTET_STRING *digest = NULL;
|
|
1636
|
+
const ASN1_OBJECT *obj = NULL;
|
|
1637
|
+
int ptype = 0;
|
|
1638
|
+
const void *pval = NULL;
|
|
1639
|
+
int ret = 0;
|
|
1640
|
+
|
|
1641
|
+
if (!input || input_len > (size_t)LONG_MAX)
|
|
1642
|
+
return 0;
|
|
1643
|
+
cursor = input;
|
|
1644
|
+
encrypted = d2i_X509_SIG(NULL, &cursor, (long)input_len);
|
|
1645
|
+
if (!encrypted || cursor != input + input_len)
|
|
1646
|
+
goto cleanup;
|
|
1647
|
+
X509_SIG_get0(encrypted, &alg, &digest);
|
|
1648
|
+
if (!alg || !digest)
|
|
1649
|
+
goto cleanup;
|
|
1650
|
+
X509_ALGOR_get0(&obj, &ptype, &pval, alg);
|
|
1651
|
+
(void)ptype;
|
|
1652
|
+
(void)pval;
|
|
1653
|
+
if (obj && OBJ_obj2nid(obj) == NID_pbes2)
|
|
1654
|
+
ret = 1;
|
|
1655
|
+
|
|
1656
|
+
cleanup:
|
|
1657
|
+
if (encrypted)
|
|
1658
|
+
X509_SIG_free(encrypted);
|
|
1659
|
+
return ret;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
int pq_pkcs8_der_to_pem(char **output, size_t *output_len, const uint8_t *der, size_t der_len,
|
|
1663
|
+
int encrypted) {
|
|
1664
|
+
return pq_der_to_pem(encrypted ? PQ_PKCS8_ENCRYPTED_PRIVATE_KEY_PEM_LABEL
|
|
1665
|
+
: PQ_PKCS8_PRIVATE_KEY_PEM_LABEL,
|
|
1666
|
+
der, der_len, output, output_len);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
int pq_pkcs8_pem_to_der(uint8_t **der_out, size_t *der_len_out, int *encrypted_out,
|
|
1670
|
+
const char *input, size_t input_len) {
|
|
1671
|
+
int ret;
|
|
1672
|
+
|
|
1673
|
+
if (!der_out || !der_len_out || !encrypted_out || !input)
|
|
1674
|
+
return PQ_ERROR_BUFFER;
|
|
1675
|
+
*der_out = NULL;
|
|
1676
|
+
*der_len_out = 0;
|
|
1677
|
+
*encrypted_out = 0;
|
|
1678
|
+
|
|
1679
|
+
ret = pq_pem_to_der(PQ_PKCS8_PRIVATE_KEY_PEM_LABEL, input, input_len, der_out, der_len_out);
|
|
1680
|
+
if (ret == PQ_SUCCESS) {
|
|
1681
|
+
*encrypted_out = 0;
|
|
1682
|
+
return PQ_SUCCESS;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
ret = pq_pem_to_der(PQ_PKCS8_ENCRYPTED_PRIVATE_KEY_PEM_LABEL, input, input_len, der_out,
|
|
1686
|
+
der_len_out);
|
|
1687
|
+
if (ret == PQ_SUCCESS) {
|
|
1688
|
+
*encrypted_out = 1;
|
|
1689
|
+
return PQ_SUCCESS;
|
|
1690
|
+
}
|
|
1691
|
+
return PQ_ERROR_BUFFER;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1162
1694
|
const char *pq_version(void) {
|
|
1163
1695
|
return PQCRYPTO_VERSION;
|
|
1164
1696
|
}
|
|
@@ -132,6 +132,26 @@ int pq_secret_key_from_pqc_container_pem(char **algorithm_out, uint8_t **key_out
|
|
|
132
132
|
size_t *key_len_out, const char *input,
|
|
133
133
|
size_t input_len);
|
|
134
134
|
|
|
135
|
+
int pq_pkcs8_private_key_info_to_der(uint8_t **output, size_t *output_len,
|
|
136
|
+
const char *oid_text, const uint8_t *private_key,
|
|
137
|
+
size_t private_key_len);
|
|
138
|
+
int pq_pkcs8_private_key_info_from_der(char **oid_text_out, uint8_t **private_key_out,
|
|
139
|
+
size_t *private_key_len_out, const uint8_t *input,
|
|
140
|
+
size_t input_len);
|
|
141
|
+
int pq_pkcs8_encrypt_private_key_info_der(uint8_t **output, size_t *output_len,
|
|
142
|
+
const uint8_t *plain_der, size_t plain_der_len,
|
|
143
|
+
const char *passphrase, size_t passphrase_len,
|
|
144
|
+
int iterations);
|
|
145
|
+
int pq_pkcs8_decrypt_private_key_info_der(uint8_t **output, size_t *output_len,
|
|
146
|
+
const uint8_t *encrypted_der,
|
|
147
|
+
size_t encrypted_der_len, const char *passphrase,
|
|
148
|
+
size_t passphrase_len);
|
|
149
|
+
int pq_pkcs8_der_is_encrypted_private_key_info(const uint8_t *input, size_t input_len);
|
|
150
|
+
int pq_pkcs8_der_to_pem(char **output, size_t *output_len, const uint8_t *der, size_t der_len,
|
|
151
|
+
int encrypted);
|
|
152
|
+
int pq_pkcs8_pem_to_der(uint8_t **der_out, size_t *der_len_out, int *encrypted_out,
|
|
153
|
+
const char *input, size_t input_len);
|
|
154
|
+
|
|
135
155
|
int pq_testing_mlkem_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
|
|
136
156
|
const uint8_t *seed, size_t seed_len);
|
|
137
157
|
int pq_testing_mlkem512_keypair_from_seed(uint8_t *public_key, uint8_t *secret_key,
|
|
@@ -6,7 +6,7 @@ mlkem_native_ref=v1.1.0
|
|
|
6
6
|
mlkem_native_commit=d2cae2be522a67bfae26100fdb520576f1b2ef90
|
|
7
7
|
mlkem_native_tree_sha256=c225de87a69e6d6360cddc4b5839b03e65fa9d5a1112a5f19700c905b7e74512
|
|
8
8
|
mldsa_native_repo=https://github.com/pq-code-package/mldsa-native.git
|
|
9
|
-
mldsa_native_ref=v1.0.0-
|
|
10
|
-
mldsa_native_commit=
|
|
11
|
-
mldsa_native_tree_sha256=
|
|
12
|
-
manifest_sha256=
|
|
9
|
+
mldsa_native_ref=v1.0.0-beta2
|
|
10
|
+
mldsa_native_commit=9b0ee84f4cf399043eca59eca4e5f8531ca1d61b
|
|
11
|
+
mldsa_native_tree_sha256=2887f59926c18a877e8c5a5e30727e84497c357032093d00d7135aedf53f011e
|
|
12
|
+
manifest_sha256=cfcf998232945760d5fd66cc3ec0af54925e13844e1758f559eeb1c7ecf16ffc
|
|
@@ -59,19 +59,14 @@ mldsa-native is used in
|
|
|
59
59
|
|
|
60
60
|
We use the [C Bounded Model Checker (CBMC)](https://github.com/diffblue/cbmc) to prove absence of various classes of undefined behaviour in C, including out of bounds memory accesses and integer overflows. The proofs cover all C code in [mldsa/src/*](mldsa) and [mldsa/src/fips202/*](mldsa/src/fips202) involved in running mldsa-native with its C backend. See [proofs/cbmc](proofs/cbmc) for details.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
HOL-Light functional correctness proofs can be found in [proofs/hol_light](proofs/hol_light). So far, the following functions have been proven correct:
|
|
65
|
-
|
|
66
|
-
- AArch64 poly_caddq [poly_caddq_asm.S](mldsa/src/native/aarch64/src/poly_caddq_asm.S)
|
|
67
|
-
- x86_64 NTT [ntt.S](mldsa/src/native/x86_64/src/ntt.S)
|
|
68
|
-
|
|
69
|
-
These proofs utilize the verification infrastructure in [s2n-bignum](https://github.com/awslabs/s2n-bignum).
|
|
62
|
+
HOL-Light functional correctness proofs can be found in [proofs/hol_light](proofs/hol_light). See the [HOL-Light README](proofs/hol_light/README.md) for the list of functions that have been proven correct. These proofs utilize the verification infrastructure in [s2n-bignum](https://github.com/awslabs/s2n-bignum).
|
|
70
63
|
|
|
71
64
|
Finally, [proofs/isabelle](proofs/isabelle/compress) contains proofs in [Isabelle/HOL](https://isabelle.in.tum.de/) of the correctness of
|
|
72
65
|
different approaches for computing the scalar decomposition routines used in ML-DSA. Those are still experimental and do not yet operate
|
|
73
66
|
on the source level.
|
|
74
67
|
|
|
68
|
+
**NOTE:** Formal Verification is never absolute. See [SOUNDNESS.md](SOUNDNESS.md) for an analysis of the scope, assumptions and risks of the formal verification efforts around mldsa-native.
|
|
69
|
+
|
|
75
70
|
## Security
|
|
76
71
|
|
|
77
72
|
All assembly in mldsa-native is constant-time in the sense that it is free of secret-dependent control flow, memory access,
|
|
@@ -81,6 +76,8 @@ timing side channels through suitable barriers and constant-time patterns.
|
|
|
81
76
|
Absence of secret-dependent branches, memory-access patterns and variable-latency instructions is also tested using `valgrind`
|
|
82
77
|
with various combinations of compilers and compilation options.
|
|
83
78
|
|
|
79
|
+
**Other attacks.** mldsa-native targets resistance against timing side-channels only. Other attack classes, such as power and electromagnetic side-channels, microarchitectural side-channels (e.g. speculative execution), or fault-injection attacks, are currently out of scope.
|
|
80
|
+
|
|
84
81
|
## Design
|
|
85
82
|
|
|
86
83
|
mldsa-native is split into a _frontend_ and two _backends_ for arithmetic and FIPS202 / SHA3. The frontend is
|
|
@@ -98,9 +95,12 @@ mldsa-native currently offers the following backends:
|
|
|
98
95
|
|
|
99
96
|
If you'd like contribute new backends, please reach out!
|
|
100
97
|
|
|
101
|
-
##
|
|
98
|
+
## Test Vectors
|
|
99
|
+
|
|
100
|
+
mldsa-native is tested against all official ACVP ML-DSA test vectors[^ACVP] and the
|
|
101
|
+
Wycheproof[^wycheproof] ML-DSA test vectors.
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
### ACVP
|
|
104
104
|
|
|
105
105
|
You can run ACVP tests using the [`tests`](./scripts/tests) script or the [ACVP client](./test/acvp/acvp_client.py) directly:
|
|
106
106
|
|
|
@@ -122,6 +122,18 @@ python3 ./test/acvp/acvp_client.py \
|
|
|
122
122
|
-e ./test/acvp/.acvp-data/v1.1.0.41/files/ML-DSA-sigVer-FIPS204/expectedResults.json
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
### Wycheproof
|
|
126
|
+
|
|
127
|
+
You can run Wycheproof[^wycheproof] tests using the [`tests`](./scripts/tests) script or the [Wycheproof client](./test/wycheproof/wycheproof_client.py) directly:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Using the tests script
|
|
131
|
+
./scripts/tests wycheproof
|
|
132
|
+
|
|
133
|
+
# Using the Wycheproof client directly
|
|
134
|
+
python3 ./test/wycheproof/wycheproof_client.py
|
|
135
|
+
```
|
|
136
|
+
|
|
125
137
|
## Benchmarking
|
|
126
138
|
|
|
127
139
|
You can measure performance, memory usage, and binary size using the [`tests`](./scripts/tests) script:
|
|
@@ -219,3 +231,4 @@ through the [PQCA Discord](https://discord.com/invite/xyVnwzfg5R). See also [CON
|
|
|
219
231
|
[^NIST_FIPS204_SEC6]: National Institute of Standards and Technology: FIPS 204 Section 6 Guidance, [https://csrc.nist.gov/csrc/media/Projects/post-quantum-cryptography/documents/faq/fips204-sec6-03192025.pdf](https://csrc.nist.gov/csrc/media/Projects/post-quantum-cryptography/documents/faq/fips204-sec6-03192025.pdf)
|
|
220
232
|
[^REF]: Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé: CRYSTALS-Dilithium reference implementation, [https://github.com/pq-crystals/dilithium/tree/master/ref](https://github.com/pq-crystals/dilithium/tree/master/ref)
|
|
221
233
|
[^tiny_sha3]: Markku-Juhani O. Saarinen: tiny_sha3, [https://github.com/mjosaarinen/tiny_sha3](https://github.com/mjosaarinen/tiny_sha3)
|
|
234
|
+
[^wycheproof]: Community Cryptography Specification Project: Project Wycheproof, [https://github.com/C2SP/wycheproof](https://github.com/C2SP/wycheproof)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[//]: # (SPDX-License-Identifier: CC-BY-4.0)
|
|
2
|
+
|
|
3
|
+
# mldsa-native source tree
|
|
4
|
+
|
|
5
|
+
This is the main source tree of mldsa-native.
|
|
6
|
+
|
|
7
|
+
## Building
|
|
8
|
+
|
|
9
|
+
To build mldsa-native for a fixed parameter set (ML-DSA-44/65/87), build the compilation units in `src/*` separately, and link to an RNG and your application. See [examples/basic](../examples/basic) for a simple example.
|
|
10
|
+
|
|
11
|
+
Alternatively, you can use the auto-generated helper files [mldsa_native.c](mldsa_native.c) and [mldsa_native_asm.S](mldsa_native_asm.S), which bundle all *.c and *.S files together. See [examples/monolithic_build](../examples/monolithic_build) and [examples/monolithic_build_native](../examples/monolithic_build_native) for examples with and without native code.
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
The build is configured by [mldsa_native_config.h](mldsa_native_config.h), or by the file pointed to by `MLD_CONFIG_FILE`. Note in particular `MLD_CONFIG_PARAMETER_SET` and `MLD_CONFIG_NAMESPACE_PREFIX`, which set the parameter set and namespace prefix, respectively.
|
|
16
|
+
|
|
17
|
+
## API
|
|
18
|
+
|
|
19
|
+
The public API is defined in [mldsa_native.h](mldsa_native.h).
|
|
20
|
+
|
|
21
|
+
## Supporting multiple parameter sets
|
|
22
|
+
|
|
23
|
+
If you want to support multiple parameter sets, build the library once per parameter set you want to support. Set `MLD_CONFIG_MULTILEVEL_WITH_SHARED` for one of the builds, and `MLD_CONFIG_MULTILEVEL_NO_SHARED` for the others, to avoid duplicating shared functionality. Finally, link with RNG and your application as before. This is demonstrated in the examples [examples/multilevel_build](../examples/multilevel_build), [examples/multilevel_build_native](../examples/multilevel_build_native), [examples/monolithic_build_multilevel](../examples/monolithic_build_multilevel) and [examples/monolithic_build_multilevel_native](../examples/monolithic_build_multilevel_native).
|