Newer
Older
XinYang_IOS / Pods / OpenVPNAdapter / Sources / OpenVPN3 / openvpn / dco / kocrypto.hpp
@zhangfeng zhangfeng on 7 Dec 2023 4 KB 1.8.0
//    OpenVPN -- An application to securely tunnel IP networks
//               over a single port, with support for SSL/TLS-based
//               session authentication and key exchange,
//               packet encryption, packet authentication, and
//               packet compression.
//
//    Copyright (C) 2012-2020 OpenVPN Inc.
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License Version 3
//    as published by the Free Software Foundation.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program in the COPYING file.
//    If not, see <http://www.gnu.org/licenses/>.

// kovpn crypto wrappers

#pragma once

#include <cstring> // for std::memset, std::memcpy
#include <utility> // for std::move

#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/frame/frame.hpp>
#include <openvpn/crypto/cryptodc.hpp>
#include <openvpn/crypto/bs64_data_limit.hpp>

namespace openvpn {
  namespace KoRekey {

    OPENVPN_EXCEPTION(korekey_error);

    struct Info {
      Info() {}

      Info(const CryptoDCContext::Ptr& dc_context_delegate_arg,
	   const unsigned int key_id_arg,
	   const Frame::Ptr& frame_arg)
	: dc_context_delegate(dc_context_delegate_arg),
	  key_id(key_id_arg),
	  frame(frame_arg)
      {
      }

      CryptoDCContext::Ptr dc_context_delegate;
      CompressContext comp_ctx;
      unsigned int key_id = 0;
      int remote_peer_id = -1;
      bool tcp_linear = false;
      StaticKey encrypt_cipher;
      StaticKey encrypt_hmac;
      StaticKey decrypt_cipher;
      StaticKey decrypt_hmac;
      Frame::Ptr frame;
    };

    class Key
    {
      // noncopyable because of "opk.primary = &key" below
      Key(const Key&) = delete;
      Key& operator=(const Key&) = delete;

    public:
      static void validate(const CryptoAlgs::Type cipher,
			   const CryptoAlgs::Type digest)
      {
	const CryptoAlgs::Alg& calg = CryptoAlgs::get(cipher);
	const CryptoAlgs::Alg& halg = CryptoAlgs::get(digest);

	switch (cipher)
	  {
	  case CryptoAlgs::AES_128_GCM:
	  case CryptoAlgs::AES_192_GCM:
	  case CryptoAlgs::AES_256_GCM:
	  case CryptoAlgs::AES_128_CBC:
	  case CryptoAlgs::AES_192_CBC:
	  case CryptoAlgs::AES_256_CBC:
	  case CryptoAlgs::BF_CBC:
#ifdef ENABLE_OVPNDCO
	  case CryptoAlgs::NONE:
#endif
	    break;
	  default:
	    OPENVPN_THROW(korekey_error, "cipher alg " << calg.name() << " is not currently supported by kovpn");
	  }

	if (calg.mode() == CryptoAlgs::CBC_HMAC)
	  {
	    switch (digest)
	      {
	      case CryptoAlgs::SHA1:
	      case CryptoAlgs::SHA256:
#ifdef ENABLE_OVPNDCO
	      case CryptoAlgs::NONE:
#endif
		break;
	      default:
		OPENVPN_THROW(korekey_error, "HMAC alg " << halg.name() << " is not currently supported by kovpn");
	      }
	  }
      }

      Key() {}

    protected:
      const unsigned char *verify_key(const char *title, const StaticKey& sk, const size_t size_required)
      {
	if (sk.size() < size_required)
	  OPENVPN_THROW(korekey_error, title << ": insufficient key material, provided=" << sk.size() << " required=" << size_required);
	return sk.data();
      }

      void set_nonce_tail(const char *title, unsigned char *dest, const size_t dest_size, const StaticKey& src)
      {
	const int NONCE_TAIL_SIZE = CryptoAlgs::AEAD_NONCE_TAIL_SIZE;

	const unsigned char *k = verify_key(title, src, NONCE_TAIL_SIZE);
	if (dest_size < NONCE_TAIL_SIZE)
	  OPENVPN_THROW(korekey_error, title << ": cannot set");
	std::memcpy(dest, k, NONCE_TAIL_SIZE);

	// if dest is larger than NONCE_TAIL_SIZE, zero remaining bytes
	if (dest_size > NONCE_TAIL_SIZE)
	  std::memset(dest + NONCE_TAIL_SIZE, 0, dest_size - NONCE_TAIL_SIZE);
      }
    };
  }
}

#ifdef ENABLE_KOVPN
#include <openvpn/kovpn/kovpnkocrypto.hpp>
#elif ENABLE_OVPNDCO
#include <openvpn/dco/ovpndcokocrypto.hpp>
#else
#error either ENABLE_KOVPN or ENABLE_OVPNDCO must be defined
#endif