mirror of
https://github.com/taosdata/TDengine
synced 2026-05-24 10:09:01 +00:00
190 lines
7.1 KiB
C
190 lines
7.1 KiB
C
/*
|
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
*
|
|
* This program is free software: you can use, redistribute, and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3
|
|
* or later ("AGPL"), 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.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _TD_COMMON_TENCRYPT_H_
|
|
#define _TD_COMMON_TENCRYPT_H_
|
|
|
|
#include "tdef.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
// ============================================================================
|
|
// Encrypted File Operations
|
|
// ============================================================================
|
|
|
|
// File encryption magic number and constants
|
|
#define TD_ENCRYPT_FILE_MAGIC "tdEncrypt"
|
|
#define TD_ENCRYPT_FILE_VERSION 1
|
|
#define TD_ENCRYPT_MAGIC_LEN 16
|
|
|
|
// Key loading timeout configuration
|
|
#define TD_ENCRYPT_KEY_WAIT_TIMEOUT_MS 30000 // 30 seconds timeout for waiting encryption key
|
|
|
|
// Database encryption status
|
|
typedef enum {
|
|
TD_DB_ENCRYPT_STATUS_UNKNOWN = 0, // Unknown - encryption state uncertain (upgrade scenario)
|
|
TD_DB_ENCRYPT_STATUS_PLAIN = 1, // Plain - database files are unencrypted
|
|
TD_DB_ENCRYPT_STATUS_ENCRYPTED = 2 // Encrypted - database files are fully encrypted
|
|
} ETdDbEncryptStatus;
|
|
|
|
// DNode encryption status
|
|
typedef enum {
|
|
TD_DNODE_ENCRYPT_STATUS_PLAIN = 0, // Plain - config and metadata files are unencrypted
|
|
TD_DNODE_ENCRYPT_STATUS_ENCRYPTED = 1 // Encrypted - all related files are encrypted
|
|
} ETdDnodeEncryptStatus;
|
|
|
|
// Encrypt file header structure (plaintext part at file beginning)
|
|
typedef struct {
|
|
char magic[TD_ENCRYPT_MAGIC_LEN]; // Magic number "tdEncrypt"
|
|
int32_t algorithm; // Encryption algorithm (e.g., TSDB_ENCRYPT_ALGO_SM4 = 1)
|
|
int32_t version; // File format version
|
|
int32_t dataLen; // Length of encrypted data following header
|
|
char reserved[32]; // Reserved for future use
|
|
} STdEncryptFileHeader;
|
|
|
|
// Encryption algorithm ID to name mapping
|
|
// Based on EEncryptAlgo enum and mnode encryption algorithm definitions
|
|
static const char *TD_ENCRYPT_ALGO_NAMES[] = {
|
|
"NONE", // 0: ENCRYPT_ALGO_NONE
|
|
"SM4-CBC:SM4", // 1: ENCRYPT_ALGO_SM4 / SM4 symmetric encryption
|
|
"AES-128-CBC", // 2: AES symmetric encryption
|
|
"SM3", // 3: ENCRYPT_ALGO_SM3 / SM3 digest
|
|
"SHA-256", // 4: SHA-256 digest
|
|
"SM2" // 5: ENCRYPT_ALGO_SM2 / SM2 asymmetric cipher
|
|
};
|
|
|
|
#define TD_ENCRYPT_ALGO_NAME_MAX 6
|
|
|
|
// Get encryption algorithm name by ID
|
|
static inline const char *taosGetEncryptAlgoName(int32_t algorithm) {
|
|
if (algorithm >= 0 && algorithm < TD_ENCRYPT_ALGO_NAME_MAX) {
|
|
return TD_ENCRYPT_ALGO_NAMES[algorithm];
|
|
}
|
|
return "UNKNOWN";
|
|
}
|
|
|
|
/**
|
|
* @brief Write file with encryption header using atomic file replacement
|
|
*
|
|
* This function writes data to a file with an encryption header at the beginning.
|
|
* The caller is responsible for encrypting the data before passing it to this function.
|
|
* It uses atomic file replacement strategy: writes to temp file, then renames.
|
|
*
|
|
* @param filepath Target file path
|
|
* @param algorithm Encryption algorithm identifier (e.g., TSDB_ENCRYPT_ALGO_SM4)
|
|
* @param data Data buffer to write (caller should encrypt data if needed, can be NULL for empty file)
|
|
* @param dataLen Length of data to write (0 for empty file)
|
|
* @return 0 on success, error code on failure
|
|
*/
|
|
int32_t taosWriteEncryptFileHeader(const char *filepath, int32_t algorithm, const void *data, int32_t dataLen);
|
|
|
|
/**
|
|
* @brief Read encryption header from file
|
|
*
|
|
* Reads and validates the encryption header from the beginning of a file.
|
|
*
|
|
* @param filepath File path to read
|
|
* @param header Output parameter for header data
|
|
* @return 0 on success, error code on failure
|
|
*/
|
|
int32_t taosReadEncryptFileHeader(const char *filepath, STdEncryptFileHeader *header);
|
|
|
|
/**
|
|
* @brief Check if file has encryption header
|
|
*
|
|
* Quickly checks if a file begins with the encryption magic number.
|
|
*
|
|
* @param filepath File path to check
|
|
* @param algorithm Output parameter for algorithm (can be NULL)
|
|
* @return true if file is encrypted, false otherwise
|
|
*/
|
|
bool taosIsEncryptedFile(const char *filepath, int32_t *algorithm);
|
|
|
|
/**
|
|
* @brief Write configuration file with encryption support
|
|
*
|
|
* Writes a configuration file with optional encryption based on tsCfgKey.
|
|
* If tsCfgKey is enabled, encrypts the data using SM4 CBC algorithm and
|
|
* writes it with an encryption header. Otherwise, writes the file normally.
|
|
*
|
|
* This function is used for transparent encryption of configuration files
|
|
* including dnode.json, mnode.json, vnode.json, snode.json, raft_config.json,
|
|
* raft_store.json, current.json, vnodes.json, and wal/meta-ver* files.
|
|
*
|
|
* @param filepath Target file path
|
|
* @param data Data buffer to write
|
|
* @param dataLen Length of data to write
|
|
* @return 0 on success, error code on failure
|
|
*/
|
|
int32_t taosWriteCfgFile(const char *filepath, const void *data, int32_t dataLen);
|
|
|
|
/**
|
|
* @brief Read configuration file with automatic decryption support.
|
|
*
|
|
* This function reads a configuration file and automatically handles decryption if needed.
|
|
* It checks if the file has an encryption header:
|
|
* - If encrypted: reads header, reads encrypted data, decrypts using tsCfgKey
|
|
* - If not encrypted: reads file content directly
|
|
*
|
|
* The caller is responsible for freeing the returned buffer.
|
|
*
|
|
* @param filepath File path to read
|
|
* @param data Output parameter for data buffer (caller must free)
|
|
* @param dataLen Output parameter for data length
|
|
* @return 0 on success, error code on failure
|
|
*/
|
|
int32_t taosReadCfgFile(const char *filepath, char **data, int32_t *dataLen);
|
|
|
|
/**
|
|
* @brief Encrypt existing configuration files that are not yet encrypted.
|
|
*
|
|
* This function scans common configuration file locations and encrypts any
|
|
* plaintext files it finds. It's called after encryption keys are loaded from mnode
|
|
* to ensure all sensitive config files are encrypted.
|
|
*
|
|
* Files checked:
|
|
* - dnode: dnode.info, dnode.json
|
|
* - mnode: mnode.json, raft_config.json, raft_store.json
|
|
* - vnode: vnodes.json
|
|
* - snode: snode.json
|
|
*
|
|
* @param dataDir Data directory path (tsDataDir)
|
|
* @return 0 on success, error code on failure
|
|
*/
|
|
int32_t taosEncryptExistingCfgFiles(const char *dataDir);
|
|
|
|
/**
|
|
* @brief Wait for encryption key to be loaded with timeout.
|
|
*
|
|
* This function checks if the CFG encryption key has been loaded successfully.
|
|
* If the key is not yet loaded, it will loop and wait until either:
|
|
* - The key is successfully loaded (returns 0)
|
|
* - The timeout period expires (returns error code)
|
|
*
|
|
* The timeout is controlled by TD_ENCRYPT_KEY_WAIT_TIMEOUT_MS macro.
|
|
* The check interval is 100ms between each attempt.
|
|
*
|
|
* @return 0 if key loaded successfully, TSDB_CODE_TIMEOUT_ERROR if timeout occurs
|
|
*/
|
|
int32_t taosWaitCfgKeyLoaded(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /*_TD_COMMON_TENCRYPT_H_*/
|
|
|