diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d75fd82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.env +libdave.so +libdave-Linux-ARM64-boringssl.zip +bin/ +obj/ diff --git a/Nb1XBot.cs b/Nb1XBot.cs new file mode 100644 index 0000000..2693f17 --- /dev/null +++ b/Nb1XBot.cs @@ -0,0 +1,75 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; +using DotNetEnv; + +class Program +{ + private DiscordSocketClient _client; + + static async Task Main(string[] args) + { + Env.Load(); + await new Program().MainAsync(); + } + + public async Task MainAsync() + { + var config = new DiscordSocketConfig() + { + GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent | GatewayIntents.GuildVoiceStates, + EnableVoiceDaveEncryption = true + }; + + _client = new DiscordSocketClient(config); + + _client.Log += LogAsync; + _client.Ready += ReadyAsync; + + var token = Environment.GetEnvironmentVariable("DISCORD_TOKEN"); + + if (string.IsNullOrEmpty(token)) + { + Console.WriteLine("[Error] Discord token is missing from the environment variables."); + return; + } + + await _client.LoginAsync(TokenType.Bot, token); + await _client.StartAsync(); + + await Task.Delay(-1); + } + + private Task LogAsync(LogMessage message) + { + Console.WriteLine($"[Discord] {message.ToString()}"); + return Task.CompletedTask; + } + + private Task ReadyAsync() + { + Console.WriteLine($"[Client] Connected successfully as {_client.CurrentUser}."); + + _ = _client.SetGameAsync("Among Us", "https://twitch.tv/mon_pseudo_twitch", ActivityType.Streaming); + + _ = Task.Run(async () => + { + try + { + await Task.Delay(2000); + + ulong guildId = 1536666691923353703; + ulong vocalId = 1540346109967208598; + + await VocalManager.ConnectToVoiceChannelAsync(_client, guildId, vocalId); + } + catch (Exception ex) + { + Console.WriteLine($"[Error] Background voice connection failed: {ex.Message}"); + } + }); + + return Task.CompletedTask; + } +} diff --git a/Vocal.cs b/Vocal.cs new file mode 100644 index 0000000..96d96e8 --- /dev/null +++ b/Vocal.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.WebSocket; + +public static class VocalManager +{ + public static async Task ConnectToVoiceChannelAsync(DiscordSocketClient client, ulong guildId, ulong vocalId) + { + var guild = client.GetGuild(guildId); + if (guild == null) + { + throw new InvalidOperationException($"Guild with ID {guildId} not found."); + } + + var channel = guild.GetVoiceChannel(vocalId); + if (channel == null) + { + throw new InvalidOperationException($"Voice channel with ID {vocalId} not found."); + } + + await channel.ConnectAsync(); + Console.WriteLine($"[Voice] Successfully connected to voice channel '{channel.Name}' in guild '{guild.Name}'."); + } +} diff --git a/libdave/include/dave/array_view.h b/libdave/include/dave/array_view.h new file mode 100644 index 0000000..28c2a32 --- /dev/null +++ b/libdave/include/dave/array_view.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +namespace discord { +namespace dave { + +template +class ArrayView { +public: + ArrayView() = default; + ArrayView(T* data, size_t size) + : data_(data) + , size_(size) + { + } + + size_t size() const { return size_; } + T* data() const { return data_; } + + T* begin() const { return data_; } + T* end() const { return data_ + size_; } + +private: + T* data_ = nullptr; + size_t size_ = 0; +}; + +template +inline ArrayView MakeArrayView(T* data, size_t size) +{ + return ArrayView(data, size); +} + +template +inline ArrayView MakeArrayView(std::vector& data) +{ + return ArrayView(data.data(), data.size()); +} + +} // namespace dave +} // namespace discord diff --git a/libdave/include/dave/dave.h b/libdave/include/dave/dave.h new file mode 100644 index 0000000..8c52ab1 --- /dev/null +++ b/libdave/include/dave/dave.h @@ -0,0 +1,636 @@ +/** + * @file dave.h + * @brief DAVE (Discord Audio/Video Encryption) C API + * + * This header provides the C API for end-to-end encryption of audio and video + * streams using the DAVE protocol. + * + * All handles are opaque pointers that must be created and destroyed using + * the corresponding API functions. Memory management rules: + * - Handles from *Create functions must be freed with their *Destroy counterpart + * - Output handles should be destroyed by the caller using the corresponding *Destroy function + * - Functions do not take ownership of the input data unless otherwise specified + * - Output byte arrays allocated by the library must be freed using daveFree() + */ + +#pragma once + +#include +#include +#include + +#if (defined(_WIN32) || defined(_WIN64)) +#define DAVE_EXPORT __declspec(dllexport) +#else +#define DAVE_EXPORT __attribute__((visibility("default"))) +#endif + +#define DECLARE_OPAQUE_HANDLE(x) typedef struct x##_s* x + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief DAVE session handle for managing group encryption state */ +DECLARE_OPAQUE_HANDLE(DAVESessionHandle); +/** @brief Result handle from processing an MLS commit message */ +DECLARE_OPAQUE_HANDLE(DAVECommitResultHandle); +/** @brief Result handle from processing an MLS welcome message */ +DECLARE_OPAQUE_HANDLE(DAVEWelcomeResultHandle); +/** @brief Key ratchet handle for deriving encryption keys */ +DECLARE_OPAQUE_HANDLE(DAVEKeyRatchetHandle); +/** @brief Media frame encryptor handle */ +DECLARE_OPAQUE_HANDLE(DAVEEncryptorHandle); +/** @brief Media frame decryptor handle */ +DECLARE_OPAQUE_HANDLE(DAVEDecryptorHandle); + +/** + * @brief Supported media codecs for encryption + */ +typedef enum { + DAVE_CODEC_UNKNOWN = 0, /**< Unknown or unspecified codec */ + DAVE_CODEC_OPUS = 1, /**< Opus audio codec */ + DAVE_CODEC_VP8 = 2, /**< VP8 video codec */ + DAVE_CODEC_VP9 = 3, /**< VP9 video codec */ + DAVE_CODEC_H264 = 4, /**< H.264/AVC video codec */ + DAVE_CODEC_H265 = 5, /**< H.265/HEVC video codec */ + DAVE_CODEC_AV1 = 6 /**< AV1 video codec */ +} DAVECodec; + +/** + * @brief Media stream type classification + */ +typedef enum { + DAVE_MEDIA_TYPE_AUDIO = 0, /**< Audio stream */ + DAVE_MEDIA_TYPE_VIDEO = 1 /**< Video stream */ +} DAVEMediaType; + +/** + * @brief Result codes returned by encryption operations + */ +typedef enum { + DAVE_ENCRYPTOR_RESULT_CODE_SUCCESS = 0, /**< Encryption succeeded */ + DAVE_ENCRYPTOR_RESULT_CODE_ENCRYPTION_FAILURE = 1, /**< Encryption failed */ + DAVE_ENCRYPTOR_RESULT_CODE_MISSING_KEY_RATCHET = 2,/**< No key ratchet available */ + DAVE_ENCRYPTOR_RESULT_CODE_MISSING_CRYPTOR = 3, /**< Missing cryptographic context */ + DAVE_ENCRYPTOR_RESULT_CODE_TOO_MANY_ATTEMPTS = 4, /**< Too many attempts to encrypt the frame failed */ +} DAVEEncryptorResultCode; + +/** + * @brief Result codes returned by decryption operations + */ +typedef enum { + DAVE_DECRYPTOR_RESULT_CODE_SUCCESS = 0, /**< Decryption succeeded */ + DAVE_DECRYPTOR_RESULT_CODE_DECRYPTION_FAILURE = 1, /**< Decryption failed */ + DAVE_DECRYPTOR_RESULT_CODE_MISSING_KEY_RATCHET = 2,/**< No key ratchet available */ + DAVE_DECRYPTOR_RESULT_CODE_INVALID_NONCE = 3, /**< Invalid nonce in encrypted frame */ + DAVE_DECRYPTOR_RESULT_CODE_MISSING_CRYPTOR = 4 /**< Missing cryptographic context */ +} DAVEDecryptorResultCode; + +/** + * @brief Log message severity levels + */ +typedef enum { + DAVE_LOGGING_SEVERITY_VERBOSE = 0, /**< Verbose debug information */ + DAVE_LOGGING_SEVERITY_INFO = 1, /**< Informational messages */ + DAVE_LOGGING_SEVERITY_WARNING = 2, /**< Warning messages */ + DAVE_LOGGING_SEVERITY_ERROR = 3, /**< Error messages */ + DAVE_LOGGING_SEVERITY_NONE = 4 /**< Messages to be ignored */ +} DAVELoggingSeverity; + +/** + * @brief Callback invoked when an MLS protocol failure occurs + * @param source The source/component where the failure occurred + * @param reason Human-readable failure reason + * @param userData User-provided context pointer + */ +typedef void (*DAVEMLSFailureCallback)(const char* source, const char* reason, void* userData); + +/** + * @brief Callback invoked with the computed pairwise fingerprint for identity verification + * @param fingerprint Pointer to fingerprint bytes (freed by the library after the callback returns) + * @param length Length of fingerprint in bytes + * @param userData User-provided context pointer + */ +typedef void (*DAVEPairwiseFingerprintCallback)(const uint8_t* fingerprint, size_t length, void* userData); + +/** + * @brief Callback invoked when the encryptor's protocol version changes + * @param userData User-provided context pointer + */ +typedef void (*DAVEEncryptorProtocolVersionChangedCallback)(void* userData); + +/** + * @brief Custom log sink callback for receiving library log messages + * @param severity Log severity level + * @param file Source file name where log originated (freed by the library after the callback returns) + * @param line Line number in source file + * @param message Log message text (freed by the library after the callback returns) + */ +typedef void (*DAVELogSinkCallback)(DAVELoggingSeverity severity, + const char* file, + int line, + const char* message); + +/** + * @brief Statistics for encryption operations + */ +typedef struct DAVEEncryptorStats { + uint64_t passthroughCount; /**< Frames passed through without encryption */ + uint64_t encryptSuccessCount; /**< Successful encryption count */ + uint64_t encryptFailureCount; /**< Failed encryption count */ + uint64_t encryptDuration; /**< Total encryption duration */ + uint64_t encryptAttempts; /**< Total encryption attempts */ + uint64_t encryptMaxAttempts; /**< Maximum retry attempts for a single frame */ + uint64_t encryptMissingKeyCount;/**< Encryptions skipped due to missing key */ +} DAVEEncryptorStats; + +/** + * @brief Statistics for decryption operations + */ +typedef struct DAVEDecryptorStats { + uint64_t passthroughCount; /**< Frames passed through without decryption */ + uint64_t decryptSuccessCount; /**< Successful decryption count */ + uint64_t decryptFailureCount; /**< Failed decryption count */ + uint64_t decryptDuration; /**< Total decryption duration */ + uint64_t decryptAttempts; /**< Total decryption attempts */ + uint64_t decryptMissingKeyCount; /**< Decryptions failed due to missing key */ + uint64_t decryptInvalidNonceCount;/**< Decryptions failed due to invalid nonce */ +} DAVEDecryptorStats; + + +/******************************************************************************* + * Version + ******************************************************************************/ + +/** + * @brief Returns the maximum protocol version supported by this library + * @return Maximum supported protocol version number + */ +DAVE_EXPORT uint16_t daveMaxSupportedProtocolVersion(void); + +/******************************************************************************* + * Memory Management + ******************************************************************************/ + +/** + * @brief Frees memory allocated by the DAVE library + * + * Use this function to free any byte arrays or buffers allocated by DAVE API + * functions. + * + * @param ptr Pointer to memory previously allocated by a DAVE API function. + * If NULL, this function does nothing. + * + * @note This function should be used to free output byte arrays from functions + * like daveSessionGetLastEpochAuthenticator, daveSessionGetMarshalledKeyPackage, + * daveCommitResultGetRosterMemberIds, etc. Do NOT use this to destroy handles; + * use the corresponding *Destroy functions instead. + */ +DAVE_EXPORT void daveFree(void* ptr); + +/******************************************************************************* + * Session Management + ******************************************************************************/ + +/** + * @brief Creates a new DAVE session + * @param context Currently unused platform-specific context pointer (can be NULL) + * @param authSessionId String used to manage persistent key lifetimes (can be NULL) + * @param callback Callback invoked on MLS failures + * @param userData User data pointer passed to the callback + * @return New session handle, or NULL on failure. Must be destroyed with daveSessionDestroy() + */ +DAVE_EXPORT DAVESessionHandle daveSessionCreate(void* context, + const char* authSessionId, + DAVEMLSFailureCallback callback, + void* userData); + +/** + * @brief Destroys a session and frees associated resources + * @param session Session handle to destroy + */ +DAVE_EXPORT void daveSessionDestroy(DAVESessionHandle session); + +/** + * @brief Initializes a session with protocol version and group information + * @param session Session handle + * @param version Protocol version to use + * @param groupId Group identifier common to all users in the group + * @param selfUserId User ID of the local user + */ +DAVE_EXPORT void daveSessionInit(DAVESessionHandle session, + uint16_t version, + uint64_t groupId, + const char* selfUserId); + +/** + * @brief Resets the session state + * @param session Session handle + */ +DAVE_EXPORT void daveSessionReset(DAVESessionHandle session); + +/** + * @brief Sets the protocol version for the session + * @param session Session handle + * @param version Protocol version to set + */ +DAVE_EXPORT void daveSessionSetProtocolVersion(DAVESessionHandle session, uint16_t version); + +/** + * @brief Gets the current protocol version of the session + * @param session Session handle + * @return Current protocol version + */ +DAVE_EXPORT uint16_t daveSessionGetProtocolVersion(DAVESessionHandle session); + +/** + * @brief Retrieves the authenticator from the last MLS epoch + * @param session Session handle + * @param[out] authenticator Output pointer to authenticator bytes (caller must free with daveFree) + * @param[out] length Output pointer to authenticator length + */ +DAVE_EXPORT void daveSessionGetLastEpochAuthenticator(DAVESessionHandle session, + uint8_t** authenticator, + size_t* length); + +/** + * @brief Sets the external sender credentials for the session + * @param session Session handle + * @param externalSender External sender credential bytes + * @param length Length of external sender data + */ +DAVE_EXPORT void daveSessionSetExternalSender(DAVESessionHandle session, + const uint8_t* externalSender, + size_t length); + +/** + * @brief Processes MLS proposals and generates commit/welcome messages + * @param session Session handle + * @param proposals Serialized proposal bytes + * @param length Length of proposals + * @param recognizedUserIds Array of recognized user ID strings + * @param recognizedUserIdsLength Number of recognized user IDs + * @param[out] commitWelcomeBytes Output buffer to commit/welcome message bytes (caller must free with daveFree) + * @param[out] commitWelcomeBytesLength Output length of the commit/welcome message + */ +DAVE_EXPORT void daveSessionProcessProposals(DAVESessionHandle session, + const uint8_t* proposals, + size_t length, + const char** recognizedUserIds, + size_t recognizedUserIdsLength, + uint8_t** commitWelcomeBytes, + size_t* commitWelcomeBytesLength); + +/** + * @brief Processes an incoming MLS commit message + * @param session Session handle + * @param commit Serialized commit message bytes + * @param length Length of commit message + * @return Commit result handle. Must be destroyed with daveCommitResultDestroy() + */ +DAVE_EXPORT DAVECommitResultHandle daveSessionProcessCommit(DAVESessionHandle session, + const uint8_t* commit, + size_t length); + +/** + * @brief Processes an incoming MLS welcome message to join a group + * @param session Session handle + * @param welcome Serialized welcome message bytes + * @param length Length of welcome message + * @param recognizedUserIds Array of recognized user ID strings + * @param recognizedUserIdsLength Number of recognized user IDs + * @return Welcome result handle. Must be destroyed with daveWelcomeResultDestroy() + */ +DAVE_EXPORT DAVEWelcomeResultHandle daveSessionProcessWelcome(DAVESessionHandle session, + const uint8_t* welcome, + size_t length, + const char** recognizedUserIds, + size_t recognizedUserIdsLength); + +/** + * @brief Gets the marshalled MLS key package for this session + * @param session Session handle + * @param[out] keyPackage Output buffer to key package bytes (caller must free with daveFree) + * @param[out] length Output length of the key package + */ +DAVE_EXPORT void daveSessionGetMarshalledKeyPackage(DAVESessionHandle session, + uint8_t** keyPackage, + size_t* length); + +/** + * @brief Gets a key ratchet for a specific user in the session + * @param session Session handle + * @param userId User ID to get key ratchet for + * @return Key ratchet handle. Must be destroyed with daveKeyRatchetDestroy() + */ +DAVE_EXPORT DAVEKeyRatchetHandle daveSessionGetKeyRatchet(DAVESessionHandle session, + const char* userId); + +/** + * @brief Computes a pairwise fingerprint for identity verification with another user + * @param session Session handle + * @param version Protocol version currently in use + * @param userId User ID of the remote user to compute the fingerprint for + * @param callback Callback to receive the fingerprint + * @param userData User data passed to callback + */ +DAVE_EXPORT void daveSessionGetPairwiseFingerprint(DAVESessionHandle session, + uint16_t version, + const char* userId, + DAVEPairwiseFingerprintCallback callback, + void* userData); + + +/******************************************************************************* + * Key Ratchet + ******************************************************************************/ + +/** + * @brief Destroys a key ratchet and frees associated resources + * @param keyRatchet Key ratchet handle to destroy + */ +DAVE_EXPORT void daveKeyRatchetDestroy(DAVEKeyRatchetHandle keyRatchet); + +/******************************************************************************* + * Commit Result + ******************************************************************************/ + +/** + * @brief Checks if processing the commit failed + * @param commitResultHandle Commit result handle + * @return true if commit processing failed + */ +DAVE_EXPORT bool daveCommitResultIsFailed(DAVECommitResultHandle commitResultHandle); + +/** + * @brief Checks if the commit should be ignored + * @param commitResultHandle Commit result handle + * @return true if commit should be ignored + */ +DAVE_EXPORT bool daveCommitResultIsIgnored(DAVECommitResultHandle commitResultHandle); + +/** + * @brief Gets the list of member IDs in the roster after the commit + * @param commitResultHandle Commit result handle + * @param[out] rosterIds Output buffer to array of roster member IDs (caller must free with daveFree) + * @param[out] rosterIdsLength Output length of the roster member IDs array + */ +DAVE_EXPORT void daveCommitResultGetRosterMemberIds(DAVECommitResultHandle commitResultHandle, + uint64_t** rosterIds, + size_t* rosterIdsLength); + +/** + * @brief Gets the signature for a specific roster member + * @param commitResultHandle Commit result handle + * @param rosterId Roster member ID + * @param[out] signature Output buffer to signature bytes (caller must free with daveFree) + * @param[out] signatureLength Output length of the signature + */ +DAVE_EXPORT void daveCommitResultGetRosterMemberSignature(DAVECommitResultHandle commitResultHandle, + uint64_t rosterId, + uint8_t** signature, + size_t* signatureLength); + +/** + * @brief Destroys a commit result and frees associated resources + * @param commitResultHandle Commit result handle to destroy + */ +DAVE_EXPORT void daveCommitResultDestroy(DAVECommitResultHandle commitResultHandle); + +/******************************************************************************* + * Welcome Result + ******************************************************************************/ + +/** + * @brief Gets the list of member IDs in the roster from the welcome message + * @param welcomeResultHandle Welcome result handle + * @param[out] rosterIds Output buffer to array of roster member IDs (caller must free with daveFree) + * @param[out] rosterIdsLength Output length of the roster member IDs array + */ +DAVE_EXPORT void daveWelcomeResultGetRosterMemberIds(DAVEWelcomeResultHandle welcomeResultHandle, + uint64_t** rosterIds, + size_t* rosterIdsLength); + +/** + * @brief Gets the signature for a specific roster member + * @param welcomeResultHandle Welcome result handle + * @param rosterId Roster member ID + * @param[out] signature Output buffer to signature bytes (caller must free with daveFree) + * @param[out] signatureLength Output length of the signature + */ +DAVE_EXPORT void daveWelcomeResultGetRosterMemberSignature(DAVEWelcomeResultHandle welcomeResultHandle, + uint64_t rosterId, + uint8_t** signature, + size_t* signatureLength); + +/** + * @brief Destroys a welcome result and frees associated resources + * @param welcomeResultHandle Welcome result handle to destroy + */ +DAVE_EXPORT void daveWelcomeResultDestroy(DAVEWelcomeResultHandle welcomeResultHandle); + +/******************************************************************************* + * Encryptor + ******************************************************************************/ + +/** + * @brief Creates a new media frame encryptor + * @return New encryptor handle. Must be destroyed with daveEncryptorDestroy() + */ +DAVE_EXPORT DAVEEncryptorHandle daveEncryptorCreate(void); + +/** + * @brief Destroys an encryptor and frees associated resources + * @param encryptor Encryptor handle to destroy + */ +DAVE_EXPORT void daveEncryptorDestroy(DAVEEncryptorHandle encryptor); + +/** + * @brief Sets the key ratchet for encryption + * @param encryptor Encryptor handle + * @param keyRatchet Key ratchet to use for encryption (does *not* take ownership) + */ +DAVE_EXPORT void daveEncryptorSetKeyRatchet(DAVEEncryptorHandle encryptor, + DAVEKeyRatchetHandle keyRatchet); + +/** + * @brief Enables or disables passthrough mode (frames pass through unencrypted) + * @param encryptor Encryptor handle + * @param passthroughMode true to enable passthrough, false to encrypt + */ +DAVE_EXPORT void daveEncryptorSetPassthroughMode(DAVEEncryptorHandle encryptor, + bool passthroughMode); + +/** + * @brief Associates an SSRC (Synchronization Source) with a specific codec + * @param encryptor Encryptor handle + * @param ssrc SSRC identifier + * @param codecType Codec type for this SSRC + */ +DAVE_EXPORT void daveEncryptorAssignSsrcToCodec(DAVEEncryptorHandle encryptor, + uint32_t ssrc, + DAVECodec codecType); + +/** + * @brief Gets the current protocol version used by the encryptor + * @param encryptor Encryptor handle + * @return Protocol version number + */ +DAVE_EXPORT uint16_t daveEncryptorGetProtocolVersion(DAVEEncryptorHandle encryptor); + +/** + * @brief Calculates the maximum ciphertext size for a given plaintext frame size + * @param encryptor Encryptor handle + * @param mediaType Media type (audio or video) + * @param frameSize Size of plaintext frame in bytes + * @return Maximum possible ciphertext size in bytes + */ +DAVE_EXPORT size_t daveEncryptorGetMaxCiphertextByteSize(DAVEEncryptorHandle encryptor, + DAVEMediaType mediaType, + size_t frameSize); + +/** + * @brief Checks if the encryptor has a key ratchet + * @param encryptor Encryptor handle + * @return true if has key ratchet, false otherwise + */ +DAVE_EXPORT bool daveEncryptorHasKeyRatchet(DAVEEncryptorHandle encryptor); + +/** + * @brief Checks if the encryptor is in passthrough mode + * @param encryptor Encryptor handle + * @return true if in passthrough mode, false otherwise + */ +DAVE_EXPORT bool daveEncryptorIsPassthroughMode(DAVEEncryptorHandle encryptor); + +/** + * @brief Encrypts a media frame + * @param encryptor Encryptor handle + * @param mediaType Media type (audio or video) + * @param ssrc SSRC of the stream + * @param frame Pointer to plaintext frame data + * @param frameLength Length of plaintext frame + * @param[out] encryptedFrame Pointer to the output buffer the encrypted frame will be written to + * @param encryptedFrameCapacity Capacity of the output buffer + * @param[out] bytesWritten Number of bytes written to the output buffer + * @return Result code indicating success or failure + */ +DAVE_EXPORT DAVEEncryptorResultCode daveEncryptorEncrypt(DAVEEncryptorHandle encryptor, + DAVEMediaType mediaType, + uint32_t ssrc, + const uint8_t* frame, + size_t frameLength, + uint8_t* encryptedFrame, + size_t encryptedFrameCapacity, + size_t* bytesWritten); + +/** + * @brief Sets a callback to be notified when the protocol version changes + * @param encryptor Encryptor handle + * @param callback Callback function + * @param userData User data passed to callback + */ +DAVE_EXPORT void daveEncryptorSetProtocolVersionChangedCallback( + DAVEEncryptorHandle encryptor, + DAVEEncryptorProtocolVersionChangedCallback callback, + void* userData); + +/** + * @brief Gets encryption statistics + * @param encryptor Encryptor handle + * @param mediaType Media type (audio or video) + * @param[out] stats Pointer to the stats structure to be filled + */ +DAVE_EXPORT void daveEncryptorGetStats(DAVEEncryptorHandle encryptor, + DAVEMediaType mediaType, + DAVEEncryptorStats* stats); + + + + +/******************************************************************************* + * Decryptor + ******************************************************************************/ + +/** + * @brief Creates a new media frame decryptor + * @return New decryptor handle. Must be destroyed with daveDecryptorDestroy() + */ +DAVE_EXPORT DAVEDecryptorHandle daveDecryptorCreate(void); + +/** + * @brief Destroys a decryptor and frees associated resources + * @param decryptor Decryptor handle to destroy + */ +DAVE_EXPORT void daveDecryptorDestroy(DAVEDecryptorHandle decryptor); + +/** + * @brief Transitions the decryptor to use a new key ratchet + * @param decryptor Decryptor handle + * @param keyRatchet New key ratchet to transition to (does *not* take ownership) + */ +DAVE_EXPORT void daveDecryptorTransitionToKeyRatchet(DAVEDecryptorHandle decryptor, + DAVEKeyRatchetHandle keyRatchet); + +/** + * @brief Transitions to or from passthrough mode + * @param decryptor Decryptor handle + * @param passthroughMode true to enable passthrough, false to decrypt + */ +DAVE_EXPORT void daveDecryptorTransitionToPassthroughMode(DAVEDecryptorHandle decryptor, + bool passthroughMode); + +/** + * @brief Decrypts an encrypted media frame + * @param decryptor Decryptor handle + * @param mediaType Media type (audio or video) + * @param encryptedFrame Pointer to the encrypted frame data + * @param encryptedFrameLength Length of the encrypted frame + * @param[out] frame Pointer to the output buffer the decrypted frame will be written to + * @param frameCapacity Capacity of the output buffer + * @param[out] bytesWritten Number of bytes written to the output buffer + * @return Result code indicating success or failure + */ +DAVE_EXPORT DAVEDecryptorResultCode daveDecryptorDecrypt(DAVEDecryptorHandle decryptor, + DAVEMediaType mediaType, + const uint8_t* encryptedFrame, + size_t encryptedFrameLength, + uint8_t* frame, + size_t frameCapacity, + size_t* bytesWritten); + +/** + * @brief Calculates the maximum plaintext size for a given ciphertext frame size + * @param decryptor Decryptor handle + * @param mediaType Media type (audio or video) + * @param encryptedFrameSize Size of encrypted frame in bytes + * @return Maximum possible plaintext size in bytes + */ +DAVE_EXPORT size_t daveDecryptorGetMaxPlaintextByteSize(DAVEDecryptorHandle decryptor, + DAVEMediaType mediaType, + size_t encryptedFrameSize); + +/** + * @brief Gets decryption statistics + * @param decryptor Decryptor handle + * @param mediaType Media type (audio or video) + * @param[out] stats Pointer to the stats structure to be filled + */ +DAVE_EXPORT void daveDecryptorGetStats(DAVEDecryptorHandle decryptor, + DAVEMediaType mediaType, + DAVEDecryptorStats* stats); + +/******************************************************************************* + * Logging + ******************************************************************************/ + +/** + * @brief Sets a global callback for receiving log messages from the library + * @param callback Log sink callback function + */ +DAVE_EXPORT void daveSetLogSinkCallback(DAVELogSinkCallback callback); + +#ifdef __cplusplus +} +#endif diff --git a/libdave/include/dave/dave_interfaces.h b/libdave/include/dave/dave_interfaces.h new file mode 100644 index 0000000..e7c6a6d --- /dev/null +++ b/libdave/include/dave/dave_interfaces.h @@ -0,0 +1,224 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mlspp { +namespace bytes_ns { +struct bytes; +}; // namespace bytes_ns + +struct SignaturePrivateKey; +} // namespace mlspp + + +namespace discord { +namespace dave { + +using EncryptorStats = DAVEEncryptorStats; +using DecryptorStats = DAVEDecryptorStats; +using KeyGeneration = uint32_t; +using EncryptionKey = ::mlspp::bytes_ns::bytes; + +class MlsKeyRatchet; + +enum MediaType : uint8_t { Audio, Video }; +enum Codec : uint8_t { Unknown, Opus, VP8, VP9, H264, H265, AV1 }; +enum LoggingSeverity { + LS_VERBOSE, + LS_INFO, + LS_WARNING, + LS_ERROR, + LS_NONE, +}; + +// Returned in std::variant when a message is hard-rejected and should trigger a reset +struct failed_t {}; + +// Returned in std::variant when a message is soft-rejected and should not trigger a reset +struct ignored_t {}; + +// Map of ID-key pairs. +// In ProcessCommit, this lists IDs whose keys have been added, changed, or removed; +// an empty value value means a key was removed. +using RosterMap = std::map>; + +// Return type for functions producing RosterMap or hard or soft failures +using RosterVariant = std::variant; + +constexpr auto kDefaultTransitionDuration = std::chrono::seconds(10); + +class IKeyRatchet { +public: + virtual ~IKeyRatchet() noexcept = default; + virtual EncryptionKey GetKey(KeyGeneration generation) noexcept = 0; + virtual void DeleteKey(KeyGeneration generation) noexcept = 0; +}; + +namespace mls { + +#if defined(__ANDROID__) +typedef JNIEnv* KeyPairContextType; +#else +typedef const char* KeyPairContextType; +#endif + +class ISession { +public: + virtual ~ISession() noexcept = default; + + virtual void Init(ProtocolVersion version, + uint64_t groupId, + std::string const& selfUserId, + std::shared_ptr<::mlspp::SignaturePrivateKey>& transientKey) noexcept = 0; + virtual void Reset() noexcept = 0; + + virtual void SetProtocolVersion(ProtocolVersion version) noexcept = 0; + virtual ProtocolVersion GetProtocolVersion() const noexcept = 0; + + virtual std::vector GetLastEpochAuthenticator() const noexcept = 0; + + virtual void SetExternalSender(std::vector const& externalSenderPackage) noexcept = 0; + + virtual std::optional> ProcessProposals( + std::vector proposals, + std::set const& recognizedUserIDs) noexcept = 0; + + virtual RosterVariant ProcessCommit(std::vector commit) noexcept = 0; + + virtual std::optional ProcessWelcome( + std::vector welcome, + std::set const& recognizedUserIDs) noexcept = 0; + + virtual std::vector GetMarshalledKeyPackage() noexcept = 0; + + virtual std::unique_ptr GetKeyRatchet( + std::string const& userId) const noexcept = 0; + + using PairwiseFingerprintCallback = std::function const&)>; + virtual void GetPairwiseFingerprint(uint16_t version, + std::string const& userId, + PairwiseFingerprintCallback callback) const noexcept = 0; +}; + +using MLSFailureCallback = std::function; +std::unique_ptr CreateSession(KeyPairContextType context, + std::string authSessionId, + MLSFailureCallback callback) noexcept; + +} // namespace mls + +class IEncryptor { +public: + enum ResultCode { + Success, + EncryptionFailure, + MissingKeyRatchet, + MissingCryptor, + TooManyAttempts, + }; + + virtual ~IEncryptor() = default; + + virtual void SetKeyRatchet(std::unique_ptr keyRatchet) = 0; + virtual void SetPassthroughMode(bool passthroughMode) = 0; + + virtual bool HasKeyRatchet() const = 0; + virtual bool IsPassthroughMode() const = 0; + + virtual void AssignSsrcToCodec(uint32_t ssrc, Codec codecType) = 0; + virtual Codec CodecForSsrc(uint32_t ssrc) = 0; + + virtual ResultCode Encrypt(MediaType mediaType, + uint32_t ssrc, + ArrayView frame, + ArrayView encryptedFrame, + size_t* bytesWritten) = 0; + + virtual size_t GetMaxCiphertextByteSize(MediaType mediaType, size_t frameSize) = 0; + virtual EncryptorStats GetStats(MediaType mediaType) const = 0; + + using ProtocolVersionChangedCallback = std::function; + virtual void SetProtocolVersionChangedCallback(ProtocolVersionChangedCallback callback) = 0; + + virtual ProtocolVersion GetProtocolVersion() const = 0; +}; + +std::unique_ptr CreateEncryptor(); + +class IDecryptor { +public: + using Duration = std::chrono::seconds; + enum ResultCode { + Success, + DecryptionFailure, + MissingKeyRatchet, + InvalidNonce, + MissingCryptor, + }; + + virtual ~IDecryptor() = default; + + virtual void TransitionToKeyRatchet(std::unique_ptr keyRatchet, + Duration transitionExpiry = kDefaultTransitionDuration) = 0; + virtual void TransitionToPassthroughMode( + bool passthroughMode, + Duration transitionExpiry = kDefaultTransitionDuration) = 0; + + virtual ResultCode Decrypt(MediaType mediaType, + ArrayView encryptedFrame, + ArrayView frame, + size_t* bytesWritten) = 0; + + virtual size_t GetMaxPlaintextByteSize(MediaType mediaType, size_t encryptedFrameSize) = 0; + virtual DecryptorStats GetStats(MediaType mediaType) const = 0; +}; + +std::unique_ptr CreateDecryptor(); + +static_assert(DAVE_CODEC_UNKNOWN == static_cast(Codec::Unknown)); +static_assert(DAVE_CODEC_OPUS == static_cast(Codec::Opus)); +static_assert(DAVE_CODEC_VP8 == static_cast(Codec::VP8)); +static_assert(DAVE_CODEC_VP9 == static_cast(Codec::VP9)); +static_assert(DAVE_CODEC_H264 == static_cast(Codec::H264)); +static_assert(DAVE_CODEC_H265 == static_cast(Codec::H265)); +static_assert(DAVE_CODEC_AV1 == static_cast(Codec::AV1)); +static_assert(DAVE_MEDIA_TYPE_AUDIO == static_cast(MediaType::Audio)); +static_assert(DAVE_MEDIA_TYPE_VIDEO == static_cast(MediaType::Video)); +static_assert(DAVE_ENCRYPTOR_RESULT_CODE_SUCCESS == static_cast(IEncryptor::Success)); +static_assert(DAVE_ENCRYPTOR_RESULT_CODE_ENCRYPTION_FAILURE == + static_cast(IEncryptor::EncryptionFailure)); +static_assert(DAVE_ENCRYPTOR_RESULT_CODE_MISSING_KEY_RATCHET == + static_cast(IEncryptor::MissingKeyRatchet)); +static_assert(DAVE_ENCRYPTOR_RESULT_CODE_MISSING_CRYPTOR == + static_cast(IEncryptor::MissingCryptor)); +static_assert(DAVE_ENCRYPTOR_RESULT_CODE_TOO_MANY_ATTEMPTS == + static_cast(IEncryptor::TooManyAttempts)); +static_assert(DAVE_DECRYPTOR_RESULT_CODE_SUCCESS == static_cast(IDecryptor::Success)); +static_assert(DAVE_DECRYPTOR_RESULT_CODE_DECRYPTION_FAILURE == + static_cast(IDecryptor::DecryptionFailure)); +static_assert(DAVE_DECRYPTOR_RESULT_CODE_MISSING_KEY_RATCHET == + static_cast(IDecryptor::MissingKeyRatchet)); +static_assert(DAVE_DECRYPTOR_RESULT_CODE_INVALID_NONCE == + static_cast(IDecryptor::InvalidNonce)); +static_assert(DAVE_DECRYPTOR_RESULT_CODE_MISSING_CRYPTOR == + static_cast(IDecryptor::MissingCryptor)); +static_assert(DAVE_LOGGING_SEVERITY_VERBOSE == static_cast(LoggingSeverity::LS_VERBOSE)); +static_assert(DAVE_LOGGING_SEVERITY_INFO == static_cast(LoggingSeverity::LS_INFO)); +static_assert(DAVE_LOGGING_SEVERITY_WARNING == static_cast(LoggingSeverity::LS_WARNING)); +static_assert(DAVE_LOGGING_SEVERITY_ERROR == static_cast(LoggingSeverity::LS_ERROR)); +static_assert(DAVE_LOGGING_SEVERITY_NONE == static_cast(LoggingSeverity::LS_NONE)); + +} // namespace dave +} // namespace discord diff --git a/libdave/include/dave/logger.h b/libdave/include/dave/logger.h new file mode 100644 index 0000000..c21bdc9 --- /dev/null +++ b/libdave/include/dave/logger.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include + +#if !defined(DISCORD_LOG) +#define DISCORD_LOG_FILE_LINE(sev, file, line) ::discord::dave::LogStreamer(sev, file, line) +#define DISCORD_LOG(sev) DISCORD_LOG_FILE_LINE(::discord::dave::sev, __FILE__, __LINE__) +#endif +namespace discord { +namespace dave { + +using LogSink = void (*)(LoggingSeverity severity, + const char* file, + int line, + const std::string& message); +void SetLogSink(LogSink sink); + +class LogStreamer { +public: + LogStreamer(LoggingSeverity severity, const char* file, int line); + ~LogStreamer(); + + template + LogStreamer& operator<<(const T& value) + { + stream_ << value; + return *this; + } + +private: + LoggingSeverity severity_; + const char* file_; + int line_; + std::ostringstream stream_; +}; + +} // namespace dave +} // namespace discord diff --git a/libdave/include/dave/version.h b/libdave/include/dave/version.h new file mode 100644 index 0000000..72f9c55 --- /dev/null +++ b/libdave/include/dave/version.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include + +namespace discord { +namespace dave { + +using ProtocolVersion = uint16_t; +using SignatureVersion = uint8_t; + +ProtocolVersion MaxSupportedProtocolVersion(); + +} // namespace dave +} // namespace discord diff --git a/libdave/licenses/boringssl b/libdave/licenses/boringssl new file mode 100644 index 0000000..fc1cebb --- /dev/null +++ b/libdave/licenses/boringssl @@ -0,0 +1,252 @@ +BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL +licensing. Files that are completely new have a Google copyright and an ISC +license. This license is reproduced at the bottom of this file. + +Contributors to BoringSSL are required to follow the CLA rules for Chromium: +https://cla.developers.google.com/clas + +Files in third_party/ have their own licenses, as described therein. The MIT +license, for third_party/fiat, which, unlike other third_party directories, is +compiled into non-test libraries, is included below. + +The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the +OpenSSL License and the original SSLeay license apply to the toolkit. See below +for the actual license texts. Actually both licenses are BSD-style Open Source +licenses. In case of any license issues related to OpenSSL please contact +openssl-core@openssl.org. + +The following are Google-internal bug numbers where explicit permission from +some authors is recorded for use of their work. (This is purely for our own +record keeping.) + 27287199 + 27287880 + 27287883 + 263291445 + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + +ISC license used for completely new code in BoringSSL: + +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + +The code in third_party/fiat carries the MIT license: + +Copyright (c) 2015-2016 the fiat-crypto authors (see +https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Licenses for support code +------------------------- + +Parts of the TLS test suite are under the Go license. This code is not included +in BoringSSL (i.e. libcrypto and libssl) when compiled, however, so +distributing code linked against BoringSSL does not trigger this license: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +BoringSSL uses the Chromium test infrastructure to run a continuous build, +trybots etc. The scripts which manage this, and the script for generating build +metadata, are under the Chromium license. Distributing code linked against +BoringSSL does not trigger this license. + +Copyright 2015 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libdave/licenses/libdave b/libdave/licenses/libdave new file mode 100644 index 0000000..a5e9ae5 --- /dev/null +++ b/libdave/licenses/libdave @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Discord + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libdave/licenses/mlspp b/libdave/licenses/mlspp new file mode 100644 index 0000000..044f922 --- /dev/null +++ b/libdave/licenses/mlspp @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2018, Cisco Systems +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libdave/licenses/nlohmann-json b/libdave/licenses/nlohmann-json new file mode 100644 index 0000000..1c1f7a6 --- /dev/null +++ b/libdave/licenses/nlohmann-json @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2022 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nb1xbot.csproj b/nb1xbot.csproj new file mode 100644 index 0000000..8fe1eef --- /dev/null +++ b/nb1xbot.csproj @@ -0,0 +1,23 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + PreserveNewest + + + +