From 315e54e63d5880ade8f2bbeb26c5f536b63faf05 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 28 Jan 2019 08:52:56 -0500 Subject: [PATCH] Add ChaCha20/Poly1305 AEAD cipher (GH #724) --- Filelist.txt | 2 + chachapoly.cpp | 91 +++++++++++++++++++++ chachapoly.h | 166 +++++++++++++++++++++++++++++++++++++++ cryptest.nmake | 98 ++++++++++++----------- cryptlib.vcxproj | 2 + cryptlib.vcxproj.filters | 12 +++ 6 files changed, 323 insertions(+), 48 deletions(-) create mode 100644 chachapoly.cpp create mode 100644 chachapoly.h diff --git a/Filelist.txt b/Filelist.txt index 84a217eb..ce1f7ca0 100644 --- a/Filelist.txt +++ b/Filelist.txt @@ -56,6 +56,8 @@ chacha.cpp chacha_avx.cpp chacha_simd.cpp chacha.h +chachapoly.cpp +chachapoly.h cham.cpp cham_simd.cpp cham.h diff --git a/chachapoly.cpp b/chachapoly.cpp new file mode 100644 index 00000000..90b2864c --- /dev/null +++ b/chachapoly.cpp @@ -0,0 +1,91 @@ +// chachapoly.cpp - written and placed in the public domain by Jeffrey Walton +// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439 + +#include "pch.h" +#include "chachapoly.h" +#include "algparam.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +void ChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) +{ + // Derive MAC key + AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0)); + + // Only the head 256-bits are used to key the MAC + SecByteBlock derived(NULLPTR, 32); + AccessSymmetricCipher().ProcessString(derived, derived.size()); + + // Set the Poly1305 key + AccessMAC().SetKey(derived, 32, params); + + // Key Cipher for bulk encryption + AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true); + AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1)); +} + +void ChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs ¶ms) +{ + CRYPTOPP_ASSERT(userKey && userKeyLength == 32); + m_userKey.Assign(userKey, userKeyLength); + + RekeyCipherAndMac(userKey, userKeyLength, params); +} + +void ChaCha20Poly1305_Base::Resync(const byte *iv, size_t len) +{ + CRYPTOPP_ASSERT(iv && len == 12); + + RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(), + MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len))); +} + +size_t ChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len) +{ + AccessMAC().Update(data, len); + return 0; +} + +void ChaCha20Poly1305_Base::AuthenticateLastHeaderBlock() +{ + const byte zero[16] = {0}; + size_t pad = 16 - (m_totalHeaderLength % 16); + AccessMAC().Update(zero, pad); +} + +void ChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock() +{ + const byte zero[16] = {0}; + size_t pad = 16 - (m_totalMessageLength % 16); + AccessMAC().Update(zero, pad); +} + +void ChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize) +{ + CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)]; + PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength); + PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength); + AccessMAC().Update(length, sizeof(length)); + + AccessMAC().TruncatedFinal(mac, macSize); +} + +void ChaCha20Poly1305_Base::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(ciphertext, message, messageLength); + TruncatedFinal(mac, macSize); +} + +bool ChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength) +{ + Resynchronize(iv, ivLength); + Update(aad, aadLength); + ProcessString(message, ciphertext, ciphertextLength); + return TruncatedVerify(mac, macLength); +} + +NAMESPACE_END diff --git a/chachapoly.h b/chachapoly.h new file mode 100644 index 00000000..b5f52dd0 --- /dev/null +++ b/chachapoly.h @@ -0,0 +1,166 @@ +// chachapoly.h - written and placed in the public domain by Jeffrey Walton +// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439 + +/// \file chachapoly.h +/// \brief ChaCha20/Poly1305-TLS AEAD cipher +/// \details ChaCha20Poly1305 is an authenticated encryption cipher that combines +/// ChaCha20TLS and Poly1305TLS. The cipher uses the IETF versions of ChaCha and +/// Poly1305 because it is defined in RFC 8439, section 2.8, AEAD_CHACHA20_POLY1305 +/// construction. +/// \sa RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. + +#ifndef CRYPTOPP_CHACHA_POLY1305_H +#define CRYPTOPP_CHACHA_POLY1305_H + +#include "cryptlib.h" +#include "authenc.h" +#include "chacha.h" +#include "poly1305.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// \brief ChaCha20Poly1305 cipher base implementation +/// \details Base implementation of the AuthenticatedSymmetricCipher interface +/// \since Crypto++ 8.1 +class ChaCha20Poly1305_Base + : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, public AuthenticatedSymmetricCipherBase +{ +public: + virtual ~ChaCha20Poly1305_Base() {} + + virtual const MessageAuthenticationCode & GetMAC() const = 0; + virtual MessageAuthenticationCode & AccessMAC() = 0; + +public: + // AuthenticatedSymmetricCipher + std::string AlgorithmName() const + {return std::string("ChaCha20/Poly1305");} + std::string AlgorithmProvider() const + {return "C++";} + size_t MinKeyLength() const + {return 32;} + size_t MaxKeyLength() const + {return 32;} + size_t DefaultKeyLength() const + {return 32;} + size_t GetValidKeyLength(size_t n) const + {CRYPTOPP_UNUSED(n); return 32;} + bool IsValidKeyLength(size_t n) const + {return n==32;} + unsigned int OptimalDataAlignment() const + {return GetSymmetricCipher().OptimalDataAlignment();} + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return 16;} + unsigned int MinIVLength() const + {return 12;} + unsigned int MaxIVLength() const + {return 12;} + unsigned int DigestSize() const + {return 16;} + lword MaxHeaderLength() const + {return LWORD_MAX;} + lword MaxMessageLength() const + {return LWORD_MAX;} + lword MaxFooterLength() const + {return 16;} + + /// \brief Encrypts and calculates a MAC in one call + /// \param ciphertext the encryption buffer + /// \param mac the mac buffer + /// \param macLength the size of the MAC buffer, in bytes + /// \param iv the iv buffer + /// \param ivLength the size of the IV buffer, in bytes + /// \param aad the AAD buffer + /// \param aadLength the size of the AAD buffer, in bytes + /// \param message the message buffer + /// \param messageLength the size of the messagetext buffer, in bytes + /// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function + /// truncates the MAC if macSize < TagSize(). + virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength); + + /// \brief Decrypts and verifies a MAC in one call + /// \param message the decryption buffer + /// \param mac the mac buffer + /// \param macLength the size of the MAC buffer, in bytes + /// \param iv the iv buffer + /// \param ivLength the size of the IV buffer, in bytes + /// \param aad the AAD buffer + /// \param aadLength the size of the AAD buffer, in bytes + /// \param cipher the cipher buffer + /// \param cipherLength the size of the ciphertext buffer, in bytes + /// \return true if the MAC is valid and the decoding succeeded, false otherwise + /// \details DecryptAndVerify() decrypts and verifies the MAC in one call. + /// message is a decryption buffer and should be at least as large as the ciphertext buffer. + /// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC + /// is truncated if macLength < TagSize(). + virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength); + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const {return false;} + unsigned int AuthenticationBlockSize() const {return 1;} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Resync(const byte *iv, size_t len); + size_t AuthenticateBlocks(const byte *data, size_t len); + void AuthenticateLastHeaderBlock(); + void AuthenticateLastConfidentialBlock(); + void AuthenticateLastFooterBlock(byte *mac, size_t macSize); + +protected: + // ChaCha20 does not stash away the user key. There's no way to restart + // ChaCha once an encryption or decryption is performed. In fact, we + // cannot even Resynchronize it correctly. Compensate here. + void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs ¶ms); + + SecByteBlock m_userKey; +}; + +/// \brief ChaCha20Poly1305 cipher final implementation +/// \details ChaCha20Poly1305 is an authenticated encryption cipher that combines +/// ChaCha20TLS and Poly1305TLS. The cipher uses the IETF versions of ChaCha and +/// Poly1305 because it is defined in RFC 8439, section 2.8, AEAD_CHACHA20_POLY1305 +/// construction. +/// \sa RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +class ChaCha20Poly1305_Final : public ChaCha20Poly1305_Base +{ +protected: + const SymmetricCipher & GetSymmetricCipher() + {return const_cast(this)->AccessSymmetricCipher();} + SymmetricCipher & AccessSymmetricCipher() + {return m_cipher;} + bool IsForwardTransformation() const + {return m_cipher.IsForwardTransformation();} + + const MessageAuthenticationCode & GetMAC() const + {return const_cast(this)->AccessMAC();} + MessageAuthenticationCode & AccessMAC() + {return m_mac;} + +private: + ChaChaTLS::Encryption m_cipher; + Poly1305TLS m_mac; +}; + +/// \brief ChaCha20Poly1305-TLS cipher mode of operation +/// \details ChaCha20Poly1305 is an authenticated encryption cipher that combines +/// ChaCha20TLS and Poly1305TLS. The cipher uses the IETF versions of ChaCha and +/// Poly1305 because it is defined in RFC 8439, section 2.8, AEAD_CHACHA20_POLY1305 +/// construction. +/// \sa RFC 8439, ChaCha20 and Poly1305 +/// for IETF Protocols. +/// \since Crypto++ 8.1 +struct ChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation +{ + typedef ChaCha20Poly1305_Final Encryption; + typedef Encryption Decryption; +}; + + +NAMESPACE_END + +#endif // CRYPTOPP_CHACHA_POLY1305_H diff --git a/cryptest.nmake b/cryptest.nmake index 1c547ed3..4840297c 100644 --- a/cryptest.nmake +++ b/cryptest.nmake @@ -25,8 +25,8 @@ # about 80% of the library, but CRYPTOPP_DLL is only used for FIPS algos. # The list of LIB_SRCS and TEST_SRCS was generated under Linux with -# "make sources | fold -w74 -s". The list of LIB_OBJS and TEST_OBJS was -# generated with "make sources | fold -w74 -s | sed 's|.cpp|.obj|g'". The +# "make sources | fold -w73 -s". The list of LIB_OBJS and TEST_OBJS was +# generated with "make sources | fold -w73 -s | sed 's|.cpp|.obj|g'". The # order of the first three object files are significant. See C++ Static # Initialization Order Fisaco on the Crypto++ wiki for details. @@ -61,29 +61,30 @@ LIB_SRCS = \ authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2.cpp \ blake2b_simd.cpp blake2s_simd.cpp blowfish.cpp blumshub.cpp camellia.cpp \ cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp chacha_avx.cpp \ - chacha_simd.cpp cham.cpp cham_simd.cpp channels.cpp cmac.cpp crc.cpp \ - crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp \ - dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp eax.cpp ec2n.cpp \ - eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp \ - filters.cpp fips140.cpp fipstest.cpp gcm.cpp gcm_simd.cpp gf256.cpp \ - gf2_32.cpp gf2n.cpp gf2n_sind.cpp gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp \ - hc256.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp \ - kalyna.cpp kalynatab.cpp keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp \ - luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp \ - mqueue.cpp mqv.cpp nbtheory.cpp neon_simd.cpp oaep.cpp osrng.cpp \ - padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp \ - ppc_power7.cpp ppc_power8.cpp ppc_power9.cpp ppc_simd.cpp pssr.cpp \ - pubkey.cpp queue.cpp rabbit.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp \ - rc6.cpp rdrand.cpp rdtables.cpp rijndael.cpp rijndael_simd.cpp ripemd.cpp \ - rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp \ - serpent.cpp sha.cpp sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp \ - shark.cpp sharkbox.cpp simeck.cpp simeck_simd.cpp simon.cpp \ - simon128_simd.cpp simon64_simd.cpp skipjack.cpp sm3.cpp sm4.cpp \ - sm4_simd.cpp sosemanuk.cpp speck.cpp speck128_simd.cpp speck64_simd.cpp \ - square.cpp squaretb.cpp sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp \ - threefish.cpp tiger.cpp tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp \ - vmac.cpp wake.cpp whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp \ - zdeflate.cpp zinflate.cpp zlib.cpp + chacha_simd.cpp chachapoly.cpp cham.cpp cham_simd.cpp channels.cpp \ + cmac.cpp crc.cpp crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp \ + dh.cpp dh2.cpp dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp \ + eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp \ + esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm.cpp \ + gcm_simd.cpp gf256.cpp gf2_32.cpp gf2n.cpp gf2n_simd.cpp gfpcrypt.cpp \ + gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp hmac.cpp \ + hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp \ + keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp lsh.cpp luc.cpp mars.cpp \ + marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp \ + nbtheory.cpp neon_simd.cpp oaep.cpp ospstore.cpp osrng.cpp padlkrng.cpp \ + panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp ppc_power7.cpp \ + ppc_power8.cpp ppc_power9.cpp ppc_simd.cpp pssr.cpp pubkey.cpp queue.cpp \ + rabbit.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp \ + rdtables.cpp rijndael.cpp rijndael_simd.cpp ripemd.cpp rng.cpp rsa.cpp \ + rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp \ + sha.cpp sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp shark.cpp \ + sharkbox.cpp simeck.cpp simeck_simd.cpp simon.cpp simon128_simd.cpp \ + simon64_simd.cpp skipjack.cpp sm3.cpp sm4.cpp sm4_simd.cpp sosemanuk.cpp \ + speck.cpp speck128_simd.cpp speck64_simd.cpp square.cpp squaretb.cpp \ + sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp \ + tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wake.cpp \ + whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp \ + zlib.cpp LIB_OBJS = \ cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj \ @@ -91,29 +92,30 @@ LIB_OBJS = \ authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2.obj \ blake2b_simd.obj blake2s_simd.obj blowfish.obj blumshub.obj camellia.obj \ cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj chacha_avx.obj \ - chacha_simd.obj cham.obj cham_simd.obj channels.obj cmac.obj crc.obj \ - crc_simd.obj darn.obj default.obj des.obj dessp.obj dh.obj dh2.obj \ - dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj eax.obj ec2n.obj \ - eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj \ - filters.obj fips140.obj fipstest.obj gcm.obj gcm_simd.obj gf256.obj \ - gf2_32.obj gf2n.obj gf2n_simd.obj gfpcrypt.obj gost.obj gzip.obj hc128.obj \ - hc256.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj \ - kalyna.obj kalynatab.obj keccak.obj keccakc.obj lea.obj lea_simd.obj \ - luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj \ - mqueue.obj mqv.obj nbtheory.obj neon_simd.obj oaep.obj osrng.obj \ - padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj \ - ppc_power7.obj ppc_power8.obj ppc_power9.obj ppc_simd.obj pssr.obj \ - pubkey.obj queue.obj rabbit.obj rabin.obj randpool.obj rc2.obj rc5.obj \ - rc6.obj rdrand.obj rdtables.obj rijndael.obj rijndael_simd.obj ripemd.obj \ - rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj \ - serpent.obj sha.obj sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj \ - shark.obj sharkbox.obj simeck.obj simeck_simd.obj simon.obj \ - simon128_simd.obj simon64_simd.obj skipjack.obj sm3.obj sm4.obj \ - sm4_simd.obj sosemanuk.obj speck.obj speck128_simd.obj speck64_simd.obj \ - square.obj squaretb.obj sse_simd.obj strciphr.obj tea.obj tftables.obj \ - threefish.obj tiger.obj tigertab.obj ttmac.obj tweetnacl.obj twofish.obj \ - vmac.obj wake.obj whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj \ - zdeflate.obj zinflate.obj zlib.obj + chacha_simd.obj chachapoly.obj cham.obj cham_simd.obj channels.obj \ + cmac.obj crc.obj crc_simd.obj darn.obj default.obj des.obj dessp.obj \ + dh.obj dh2.obj dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj \ + eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj \ + esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm.obj \ + gcm_simd.obj gf256.obj gf2_32.obj gf2n.obj gf2n_simd.obj gfpcrypt.obj \ + gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj hmac.obj \ + hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj \ + keccak.obj keccakc.obj lea.obj lea_simd.obj lsh.obj luc.obj mars.obj \ + marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj \ + nbtheory.obj neon_simd.obj oaep.obj ospstore.obj osrng.obj padlkrng.obj \ + panama.obj pkcspad.obj poly1305.obj polynomi.obj ppc_power7.obj \ + ppc_power8.obj ppc_power9.obj ppc_simd.obj pssr.obj pubkey.obj queue.obj \ + rabbit.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj \ + rdtables.obj rijndael.obj rijndael_simd.obj ripemd.obj rng.obj rsa.obj \ + rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj \ + sha.obj sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj shark.obj \ + sharkbox.obj simeck.obj simeck_simd.obj simon.obj simon128_simd.obj \ + simon64_simd.obj skipjack.obj sm3.obj sm4.obj sm4_simd.obj sosemanuk.obj \ + speck.obj speck128_simd.obj speck64_simd.obj square.obj squaretb.obj \ + sse_simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj \ + tigertab.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wake.obj \ + whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj \ + zlib.obj ASM_OBJS = \ rdrand-x86.obj rdrand-x64.obj x64masm.obj x64dll.obj diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj index 50ed5447..7c99e338 100644 --- a/cryptlib.vcxproj +++ b/cryptlib.vcxproj @@ -198,6 +198,7 @@ true AdvancedVectorExtensions2 + @@ -404,6 +405,7 @@ + diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters index 6256e62b..c30ef7f9 100644 --- a/cryptlib.vcxproj.filters +++ b/cryptlib.vcxproj.filters @@ -95,6 +95,9 @@ Source Files + + Source Files + Source Files @@ -1017,11 +1020,20 @@ Header Files + + Header Files + Source Files + + Source Files + + + Source Files + Miscellaneous