diff --git a/WORKSPACE b/WORKSPACE index 70091106..ab4ec0a7 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -15,17 +15,3 @@ rules_foreign_cc_dependencies( register_preinstalled_tools = True, ) -load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") - -# Hedron's Compile Commands Extractor for Bazel -# https://github.com/hedronvision/bazel-compile-commands-extractor -git_repository( - name = "hedron_compile_commands", - commit = "1d21dc390e20ecb24d73e9dbb439e971e0d30337", - remote = "https://gitee.com/anakin-xc/bazel-compile-commands-extractor.git", - shallow_since = "1644967664 -0800", -) - -load("@hedron_compile_commands//:workspace_setup.bzl", "hedron_compile_commands_setup") - -hedron_compile_commands_setup() diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 92275357..78a6d032 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -2,6 +2,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + def yasl_deps(): _rule_python() _rules_foreign_cc() diff --git a/yasl/crypto/asymmetric_util.cc b/yasl/crypto/asymmetric_util.cc index 33b35a0f..d6e10a80 100644 --- a/yasl/crypto/asymmetric_util.cc +++ b/yasl/crypto/asymmetric_util.cc @@ -144,13 +144,21 @@ UniqueRsa CreateRsaFromX509(ByteContainerView x509_public_key) { return UniqueRsa(rsa, ::RSA_free); } -std::string GetPublicKeyFromRsa(const UniqueRsa& rsa) { +std::string GetPublicKeyFromRsa(const UniqueRsa& rsa, bool x509_pkey) { std::string public_key; { UniqueBio bio(BIO_new(BIO_s_mem()), BIO_free); YASL_ENFORCE(bio, "New bio failed."); - YASL_ENFORCE(PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()), - "Write public key failed."); + if (x509_pkey) { + UniqueEVP unique_pkey(EVP_PKEY_new(), ::EVP_PKEY_free); + YASL_ENFORCE(EVP_PKEY_set1_RSA(unique_pkey.get(), rsa.get()), + "Convert rsa to pubkey failed."); + YASL_ENFORCE(PEM_write_bio_PUBKEY(bio.get(), unique_pkey.get()), + "Write public key failed."); + } else { + YASL_ENFORCE(PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()), + "Write public key failed."); + } int size = BIO_pending(bio.get()); YASL_ENFORCE_GT(size, 0, "Bad key size."); public_key.resize(size); @@ -160,7 +168,7 @@ std::string GetPublicKeyFromRsa(const UniqueRsa& rsa) { return public_key; } -std::tuple CreateRsaKeyPair() { +std::tuple CreateRsaKeyPair(bool x509_pkey) { std::unique_ptr exp(BN_new(), BN_free); YASL_ENFORCE_EQ(BN_set_word(exp.get(), RSA_F4), 1, "BN_set_word failed."); UniqueRsa rsa(RSA_new(), RSA_free); @@ -168,7 +176,7 @@ std::tuple CreateRsaKeyPair() { RSA_generate_key_ex(rsa.get(), kRsaKeyBitSize, exp.get(), nullptr), "Generate rsa key pair failed."); - std::string public_key = GetPublicKeyFromRsa(rsa); + std::string public_key = GetPublicKeyFromRsa(rsa, x509_pkey); std::string private_key; { @@ -211,7 +219,7 @@ std::tuple CreateRsaCertificateAndPrivateKey( // - random serial number std::random_device rd; YASL_ENFORCE(ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), rd()) == 1, - "ASN1_INTEGER_set failed"); + "ASN1_INTEGER_set failed."); // 3.2 valid range X509_gmtime_adj(X509_get_notBefore(x509.get()), 0); X509_gmtime_adj(X509_get_notAfter(x509.get()), days * kSecondsInDay); @@ -232,7 +240,7 @@ std::tuple CreateRsaCertificateAndPrivateKey( // 3.5 self-signed: issuer name == name. YASL_ENFORCE(X509_set_issuer_name(x509.get(), name) == 1, - "X509_set_issuer_name failed"); + "X509_set_issuer_name failed."); AddX509Extension(x509.get(), NID_basic_constraints, (char*)"CA:TRUE"); AddX509Extension(x509.get(), NID_subject_key_identifier, (char*)"hash"); // 3.6 Do self signing with sha256-rsa. diff --git a/yasl/crypto/asymmetric_util.h b/yasl/crypto/asymmetric_util.h index 569946c0..55a8bf9e 100644 --- a/yasl/crypto/asymmetric_util.h +++ b/yasl/crypto/asymmetric_util.h @@ -40,10 +40,11 @@ UniquePkey CreatePubPkeyFromSm2Pem(ByteContainerView pem); std::tuple CreateSm2KeyPair(); -std::tuple CreateRsaKeyPair(); +std::tuple CreateRsaKeyPair(bool x509_pkey = false); UniqueRsa CreateRsaFromX509(ByteContainerView x509_public_key); -std::string GetPublicKeyFromRsa(const UniqueRsa& rsa); + +std::string GetPublicKeyFromRsa(const UniqueRsa& rsa, bool x509_pkey = false); std::tuple CreateRsaCertificateAndPrivateKey( const std::unordered_map& subject_map, diff --git a/yasl/crypto/symmetric_crypto.cc b/yasl/crypto/symmetric_crypto.cc index 9005d185..fc592ad1 100644 --- a/yasl/crypto/symmetric_crypto.cc +++ b/yasl/crypto/symmetric_crypto.cc @@ -18,14 +18,13 @@ #include "openssl/crypto.h" #include "openssl/err.h" #include "openssl/evp.h" +#include "spdlog/spdlog.h" #include "yasl/base/exception.h" namespace yasl { namespace { -constexpr size_t kBatchSize = 1024; - const EVP_CIPHER* CreateEvpCipher(SymmetricCrypto::CryptoType type) { switch (type) { case SymmetricCrypto::CryptoType::AES128_ECB: @@ -124,21 +123,18 @@ void SymmetricCrypto::Decrypt(absl::Span ciphertext, EVP_CIPHER_CTX_copy(ctx, dec_ctx_); } - size_t left = plaintext.size(); - size_t i = 0; - - while (left > 0) { - int n = std::min(left, kBatchSize); - int out_length; - int rc = - EVP_CipherUpdate(ctx, plaintext.data() + i * kBatchSize, &out_length, - ciphertext.data() + i * kBatchSize, n); - YASL_ENFORCE(rc, "Fail to decrypt, rc={}", rc); - i++; - left -= n; - } + EVP_CIPHER_CTX_set_padding(ctx, plaintext.size() % BlockSize()); + + int out_length; + int rc = EVP_CipherUpdate(ctx, plaintext.data(), &out_length, + ciphertext.data(), ciphertext.size()); + YASL_ENFORCE(rc, "Fail to decrypt, rc={}", rc); // Does not require `Finalize` for aligned inputs. + if (plaintext.size() % BlockSize() != 0) { + rc = EVP_CipherFinal(ctx, plaintext.data() + out_length, &out_length); + YASL_ENFORCE(rc, "Fail to finalize decrypt, rc={}", rc); + } if ((type_ != SymmetricCrypto::CryptoType::AES128_ECB) && (type_ != SymmetricCrypto::CryptoType::SM4_ECB)) { @@ -166,20 +162,18 @@ void SymmetricCrypto::Encrypt(absl::Span plaintext, EVP_CIPHER_CTX_copy(ctx, enc_ctx_); } - size_t left = plaintext.size(); - size_t i = 0; - - while (left > 0) { - int n = std::min(left, kBatchSize); - int outlen; - int rc = EVP_CipherUpdate(ctx, ciphertext.data() + i * kBatchSize, &outlen, - plaintext.data() + i * kBatchSize, n); - YASL_ENFORCE(rc, "Fail to encrypt, rc={}", rc); - i++; - left -= n; - } + EVP_CIPHER_CTX_set_padding(ctx, ciphertext.size() % BlockSize()); + + int outlen; + int rc = EVP_CipherUpdate(ctx, ciphertext.data(), &outlen, plaintext.data(), + plaintext.size()); + YASL_ENFORCE(rc, "Fail to encrypt, rc={}", rc); // Does not require `Finalize` for aligned inputs. + if (ciphertext.size() % BlockSize() != 0) { + rc = EVP_CipherFinal(ctx, ciphertext.data() + outlen, &outlen); + YASL_ENFORCE(rc, "Fail to finalize encrypt, rc={}", rc); + } if ((type_ != SymmetricCrypto::CryptoType::AES128_ECB) && (type_ != SymmetricCrypto::CryptoType::SM4_ECB)) { diff --git a/yasl/crypto/symmetric_crypto.h b/yasl/crypto/symmetric_crypto.h index f4c860ea..cec7f176 100644 --- a/yasl/crypto/symmetric_crypto.h +++ b/yasl/crypto/symmetric_crypto.h @@ -29,11 +29,8 @@ namespace yasl { namespace internal { -inline std::vector EcbMakeContentBlocks(uint128_t count, - int nblocks) { - std::vector ret(nblocks); - std::iota(ret.begin(), ret.end(), count); - return ret; +inline void EcbMakeContentBlocks(uint128_t count, absl::Span buf) { + std::iota(buf.begin(), buf.end(), count); } } // namespace internal @@ -119,34 +116,48 @@ inline uint64_t FillPseudoRandom(SymmetricCrypto::CryptoType crypto_type, const size_t nblock = (nbytes + block_size - 1) / block_size; const size_t padding_bytes = nbytes % block_size; - SymmetricCrypto crypto(crypto_type, seed, iv); + bool isCTR = (crypto_type == SymmetricCrypto::CryptoType::AES128_CTR || + crypto_type == SymmetricCrypto::CryptoType::SM4_CTR); - if (padding_bytes == 0) { - // No padding, fast path - crypto.Encrypt( - internal::EcbMakeContentBlocks(count, nblock), - absl::MakeSpan(reinterpret_cast(out.data()), nblock)); + std::unique_ptr crypto; + if (isCTR) { + // CTR mode does not requires padding or manully build counter... + crypto = std::make_unique(crypto_type, seed, count); + std::memset(out.data(), 0, nbytes); + auto bv = absl::MakeSpan(reinterpret_cast(out.data()), nbytes); + crypto->Encrypt(bv, bv); } else { - if (crypto_type == SymmetricCrypto::CryptoType::AES128_ECB || - crypto_type == SymmetricCrypto::CryptoType::SM4_ECB) { - if (nblock > 1) { - // first n-1 block - crypto.Encrypt(internal::EcbMakeContentBlocks(count, nblock - 1), - absl::MakeSpan(reinterpret_cast(out.data()), - nblock - 1)); - } - // last padding block - uint128_t padding = count + nblock - 1; - padding = crypto.Encrypt(padding); - std::memcpy(reinterpret_cast(out.data()) + (nblock - 1), - &padding, padding_bytes); + crypto = std::make_unique(crypto_type, seed, iv); + if (padding_bytes == 0) { + // No padding, fast path + auto s = absl::MakeSpan(reinterpret_cast(out.data()), nblock); + internal::EcbMakeContentBlocks(count, s); + crypto->Encrypt(s, s); } else { - std::vector cipher(nblock); - crypto.Encrypt(internal::EcbMakeContentBlocks(count, nblock), - absl::MakeSpan(cipher)); - std::memcpy(out.data(), cipher.data(), nbytes); + if (crypto_type == SymmetricCrypto::CryptoType::AES128_ECB || + crypto_type == SymmetricCrypto::CryptoType::SM4_ECB) { + if (nblock > 1) { + // first n-1 block + auto s = absl::MakeSpan(reinterpret_cast(out.data()), + nblock - 1); + internal::EcbMakeContentBlocks(count, s); + crypto->Encrypt(s, s); + } + // last padding block + uint128_t padding = count + nblock - 1; + padding = crypto->Encrypt(padding); + std::memcpy(reinterpret_cast(out.data()) + (nblock - 1), + &padding, padding_bytes); + } else { + std::vector cipher(nblock); + auto s = absl::MakeSpan(cipher); + internal::EcbMakeContentBlocks(count, s); + crypto->Encrypt(s, s); + std::memcpy(out.data(), cipher.data(), nbytes); + } } } + return count + nblock; } diff --git a/yasl/crypto/symmetric_crypto_test.cc b/yasl/crypto/symmetric_crypto_test.cc index 4f1ff8c1..33e61d6a 100644 --- a/yasl/crypto/symmetric_crypto_test.cc +++ b/yasl/crypto/symmetric_crypto_test.cc @@ -211,21 +211,32 @@ TEST(SymmetricCrypto, WrongKey) { TEST(SymmetricCrypto, PartialBlock) { for (auto type : kTestTypes) { - if ((type == SymmetricCrypto::CryptoType::AES128_CTR) || - (type == SymmetricCrypto::CryptoType::SM4_CTR)) - continue; + bool isCTR = ((type == SymmetricCrypto::CryptoType::AES128_CTR) || + (type == SymmetricCrypto::CryptoType::SM4_CTR)); SymmetricCrypto crypto(type, kKey1, kIv1); auto plaintext = MakeVector(SymmetricCrypto::BlockSize() - 1); std::vector encrypted(plaintext.size()); - ASSERT_THROW(crypto.Encrypt(plaintext, absl::MakeSpan(encrypted)), - Exception); + if (!isCTR) { + ASSERT_THROW(crypto.Encrypt(plaintext, absl::MakeSpan(encrypted)), + Exception); + } else { + crypto.Encrypt(plaintext, absl::MakeSpan(encrypted)); + } SymmetricCrypto crypto2(type, kKey1, kIv1); std::vector decrypted(encrypted.size()); - ASSERT_THROW(crypto2.Decrypt(absl::MakeConstSpan(encrypted), - absl::MakeSpan(decrypted)), - Exception); - EXPECT_NE(decrypted, plaintext); + if (!isCTR) { + ASSERT_THROW(crypto2.Decrypt(absl::MakeConstSpan(encrypted), + absl::MakeSpan(decrypted)), + Exception); + } else { + crypto2.Decrypt(absl::MakeConstSpan(encrypted), + absl::MakeSpan(decrypted)); + } + if (isCTR) { + // Partial block should work under CRT mode + EXPECT_EQ(decrypted, plaintext); + } } }