LCOV - code coverage report
Current view: top level - core/crypto - SPCrypto.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 17 94.1 %
Date: 2024-05-12 00:16:13 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_CRYPTO_SPCRYPTO_H_
      25             : #define STAPPLER_CRYPTO_SPCRYPTO_H_
      26             : 
      27             : #include "SPIO.h"
      28             : #include "SPBytesView.h"
      29             : #include "SPCoreCrypto.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler::crypto {
      32             : 
      33             : // Гарантирует единственность шифротекста для разных бэкэндов в блочных шифрах
      34             : // ценой производетльности. Если выключено - шифротексты могут различаться
      35             : // (при этом сохраняется интероперабельность)
      36             : #if DEBUG
      37             : constexpr bool SafeBlockEncoding = true;
      38             : #else
      39             : constexpr bool SafeBlockEncoding = false;
      40             : #endif
      41             : 
      42             : constexpr size_t BlockKeySize256 = 32; // 256-bit
      43             : 
      44             : class PublicKey;
      45             : 
      46             : enum class Backend : uint32_t {
      47             :         Default,
      48             :         MbedTLS,
      49             :         OpenSSL,
      50             :         GnuTLS,
      51             :         Custom = 32,
      52             :         Embedded = maxOf<uint32_t>() - 1
      53             : };
      54             : 
      55             : enum class BackendFlags {
      56             :         None = 0,
      57             :         SecureLibrary = 1 << 0,
      58             :         SupportsPKCS1 = 1 << 1,
      59             :         SupportsPKCS8 = 1 << 2,
      60             :         SupportsECDSA = 1 << 3,
      61             :         SupportsAes = 1 << 4,
      62             :         SupportsGost3412_2015 = 1 << 5,
      63             :         SupportsGost3410_2012 = 1 << 6, // ЭЦП
      64             : };
      65             : 
      66             : SP_DEFINE_ENUM_AS_MASK(BackendFlags)
      67             : 
      68             : enum class BlockCipher : uint16_t {
      69             :         AES_CBC,
      70             :         AES_CFB8,
      71             :         Gost3412_2015_CTR_ACPKM
      72             : };
      73             : 
      74             : enum class KeyType : uint32_t {
      75             :         Unknown,
      76             :         RSA,
      77             :         DSA,
      78             :         ECDSA,
      79             :         GOST3410_2012_256,
      80             :         GOST3410_2012_512,
      81             :         EDDSA_ED448,
      82             : };
      83             : 
      84             : enum class HashFunction {
      85             :         SHA_2,
      86             :         GOST_3411,
      87             : };
      88             : 
      89             : enum class SignAlgorithm {
      90             :         RSA_SHA256,
      91             :         RSA_SHA512,
      92             :         ECDSA_SHA256,
      93             :         ECDSA_SHA512,
      94             :         GOST_256, // GOST R 34.11-2012 256 bit
      95             :         GOST_512, // GOST R 34.11-2012 512 bit
      96             : };
      97             : 
      98             : enum class KeyBits {
      99             :         _1024,
     100             :         _2048,
     101             :         _4096
     102             : };
     103             : 
     104             : enum class KeyFormat {
     105             :         PKCS1,
     106             :         PKCS8,
     107             :         RSA = PKCS1,
     108             : };
     109             : 
     110             : struct KeyContext {
     111             :         void *cryptoCtx = nullptr;
     112             :         void *keyCtx = nullptr;
     113             :         uint32_t padding = 0;
     114             :         KeyType type = KeyType::Unknown;
     115             :         void *backendCtx = nullptr;
     116             : };
     117             : 
     118             : struct BlockKey256 {
     119         125 :         uint16_t version = 0; // keygen version
     120         125 :         BlockCipher cipher = BlockCipher::AES_CBC;
     121         125 :         std::array<uint8_t, BlockKeySize256> data = { 0 };
     122             : 
     123         125 :         bool operator==(const BlockKey256 &) const = default;
     124         125 :         bool operator!=(const BlockKey256 &) const = default;
     125             : };
     126             : 
     127             : struct BlockCryptoHeader {
     128             :         uint64_t size;
     129             :         uint16_t version;
     130             :         uint16_t cipher;
     131             :         uint32_t padding;
     132             : };
     133             : 
     134             : struct BlockInfo {
     135             :         uint64_t dataSize = 0;
     136             :         uint16_t version = 0; // keygen version
     137             :         BlockCipher cipher = BlockCipher::AES_CBC;
     138             : };
     139             : 
     140             : class PrivateKey {
     141             : public:
     142             :         PrivateKey(Backend = Backend::Default);
     143             :         PrivateKey(Backend, BytesView, const CoderSource & passwd = CoderSource());
     144             :         PrivateKey(BytesView, const CoderSource & passwd = CoderSource());
     145             :         ~PrivateKey();
     146             : 
     147             :         PrivateKey(const PrivateKey &) = delete;
     148             :         PrivateKey& operator=(const PrivateKey &) = delete;
     149             : 
     150             :         PrivateKey(PrivateKey &&);
     151             :         PrivateKey& operator=(PrivateKey &&);
     152             : 
     153             :         bool generate(KeyType type = KeyType::RSA);
     154             :         bool generate(KeyBits = KeyBits::_2048, KeyType type = KeyType::RSA);
     155             : 
     156             :         bool import(BytesView, const CoderSource & passwd = CoderSource());
     157             : 
     158             :         PublicKey exportPublic() const;
     159             : 
     160             :         Backend getBackend() const;
     161        1425 :         KeyContext getKey() const { return _key; }
     162        2000 :         KeyType getType() const { return _key.type; }
     163             : 
     164        1250 :         explicit operator bool () const { return _valid && _loaded; }
     165             : 
     166             :         bool exportPem(const Callback<void(BytesView)> &, KeyFormat = KeyFormat::PKCS8, const CoderSource &passPhrase = StringView()) const;
     167             :         bool exportPem(const Callback<void(BytesView)> &, const CoderSource &passPhrase) const;
     168             : 
     169             :         bool exportDer(const Callback<void(BytesView)> &, KeyFormat = KeyFormat::PKCS8, const CoderSource &passPhrase = StringView()) const;
     170             :         bool exportDer(const Callback<void(BytesView)> &, const CoderSource &passPhrase) const;
     171             : 
     172             :         bool sign(const Callback<void(BytesView)> &, const CoderSource &, SignAlgorithm = SignAlgorithm::RSA_SHA512) const;
     173             :         bool verify(const CoderSource &data, BytesView signature, SignAlgorithm) const;
     174             : 
     175             :         bool fingerprint(const Callback<void(BytesView)> &, const CoderSource &) const;
     176             : 
     177             :         bool isGenerateSupported(KeyType) const;
     178             :         bool isSupported(KeyFormat) const;
     179             : 
     180             :         bool encrypt(const Callback<void(BytesView)> &, const CoderSource &);
     181             :         bool decrypt(const Callback<void(BytesView)> &, const CoderSource &);
     182             : 
     183             : protected:
     184             :         bool _loaded = false;
     185             :         bool _valid = false;
     186             :         KeyContext _key;
     187             : };
     188             : 
     189             : class PublicKey {
     190             : public:
     191             :         PublicKey(Backend = Backend::Default);
     192             :         PublicKey(Backend, BytesView);
     193             :         PublicKey(BytesView);
     194             :         PublicKey(const PrivateKey &);
     195             :         ~PublicKey();
     196             : 
     197             :         PublicKey(const PublicKey &) = delete;
     198             :         PublicKey& operator=(const PublicKey &) = delete;
     199             : 
     200             :         PublicKey(PublicKey &&);
     201             :         PublicKey& operator=(PublicKey &&);
     202             : 
     203             :         bool import(BytesView);
     204             :         bool importOpenSSH(StringView);
     205             : 
     206             :         Backend getBackend() const;
     207             :         KeyContext getKey() const { return _key; }
     208          50 :         KeyType getType() const { return _key.type; }
     209             : 
     210         925 :         explicit operator bool () const { return _valid && _loaded; }
     211             : 
     212             :         bool exportPem(const Callback<void(BytesView)> &) const; // only pkcs8
     213             :         bool exportDer(const Callback<void(BytesView)> &) const; // only pkcs8
     214             : 
     215             :         bool verify(const CoderSource &data, BytesView signature, SignAlgorithm) const;
     216             : 
     217             :         bool encrypt(const Callback<void(BytesView)> &, const CoderSource &);
     218             : 
     219             : protected:
     220             :         bool _loaded = false;
     221             :         bool _valid = false;
     222             :         KeyContext _key;
     223             : };
     224             : 
     225         975 : inline constexpr size_t getBlockSize(BlockCipher c) {
     226         975 :         switch (c) {
     227         475 :         case BlockCipher::AES_CBC:
     228             :         case BlockCipher::AES_CFB8:
     229         475 :                 return 16;
     230             :                 break;
     231         500 :         case BlockCipher::Gost3412_2015_CTR_ACPKM:
     232         500 :                 return 16;
     233             :                 break;
     234             :         }
     235           0 :         return 16;
     236             : }
     237             : 
     238             : void listBackends(const Callback<void(Backend, StringView, BackendFlags)> &);
     239             : 
     240             : bool isPemKey(BytesView data);
     241             : 
     242             : bool encryptBlock(const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
     243             : bool encryptBlock(Backend b, const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
     244             : 
     245             : bool decryptBlock(const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
     246             : bool decryptBlock(Backend b, const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
     247             : 
     248             : BlockKey256 makeBlockKey(Backend, BytesView pkey, BytesView hash, BlockCipher = BlockCipher::AES_CBC, uint32_t version = 2);
     249             : BlockKey256 makeBlockKey(BytesView pkey, BytesView hash, BlockCipher = BlockCipher::AES_CBC, uint32_t version = 2);
     250             : BlockKey256 makeBlockKey(const PrivateKey &pkey, BytesView hash, uint32_t version = 2);
     251             : BlockKey256 makeBlockKey(const PrivateKey &pkey, BytesView hash, BlockCipher, uint32_t version = 2);
     252             : 
     253             : // get keygen version from encrypted block
     254             : BlockInfo getBlockInfo(BytesView);
     255             : 
     256             : using HashCoderCallback = const Callback<bool(const CoderSource &)>;
     257             : 
     258             : Sha256::Buf hash256(Backend, const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
     259             : Sha256::Buf hash256(const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
     260             : Sha256::Buf hash256(Backend, const CoderSource &, HashFunction func = HashFunction::SHA_2);
     261             : Sha256::Buf hash256(const CoderSource &, HashFunction func = HashFunction::SHA_2);
     262             : 
     263             : Sha512::Buf hash512(Backend, const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
     264             : Sha512::Buf hash512(const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
     265             : Sha512::Buf hash512(Backend, const CoderSource &, HashFunction func = HashFunction::SHA_2);
     266             : Sha512::Buf hash512(const CoderSource &, HashFunction func = HashFunction::SHA_2);
     267             : 
     268             : }
     269             : 
     270             : #endif /* STAPPLER_CRYPTO_SPCRYPTO_H_ */

Generated by: LCOV version 1.14