/src/tdengine/include/common/tencrypt.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com> |
3 | | * |
4 | | * This program is free software: you can use, redistribute, and/or modify |
5 | | * it under the terms of the GNU Affero General Public License, version 3 |
6 | | * or later ("AGPL"), as published by the Free Software Foundation. |
7 | | * |
8 | | * This program is distributed in the hope that it will be useful, but WITHOUT |
9 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
10 | | * FITNESS FOR A PARTICULAR PURPOSE. |
11 | | * |
12 | | * You should have received a copy of the GNU Affero General Public License |
13 | | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
14 | | */ |
15 | | |
16 | | #ifndef _TD_COMMON_TENCRYPT_H_ |
17 | | #define _TD_COMMON_TENCRYPT_H_ |
18 | | |
19 | | #include "tdef.h" |
20 | | |
21 | | #ifdef __cplusplus |
22 | | extern "C" { |
23 | | #endif |
24 | | |
25 | | // ============================================================================ |
26 | | // Encrypted File Operations |
27 | | // ============================================================================ |
28 | | |
29 | | // File encryption magic number and constants |
30 | 0 | #define TD_ENCRYPT_FILE_MAGIC "tdEncrypt" |
31 | 0 | #define TD_ENCRYPT_FILE_VERSION 1 |
32 | | #define TD_ENCRYPT_MAGIC_LEN 16 |
33 | | |
34 | | // Key loading timeout configuration |
35 | | #define TD_ENCRYPT_KEY_WAIT_TIMEOUT_MS 30000 // 30 seconds timeout for waiting encryption key |
36 | | |
37 | | // Database encryption status |
38 | | typedef enum { |
39 | | TD_DB_ENCRYPT_STATUS_UNKNOWN = 0, // Unknown - encryption state uncertain (upgrade scenario) |
40 | | TD_DB_ENCRYPT_STATUS_PLAIN = 1, // Plain - database files are unencrypted |
41 | | TD_DB_ENCRYPT_STATUS_ENCRYPTED = 2 // Encrypted - database files are fully encrypted |
42 | | } ETdDbEncryptStatus; |
43 | | |
44 | | // DNode encryption status |
45 | | typedef enum { |
46 | | TD_DNODE_ENCRYPT_STATUS_PLAIN = 0, // Plain - config and metadata files are unencrypted |
47 | | TD_DNODE_ENCRYPT_STATUS_ENCRYPTED = 1 // Encrypted - all related files are encrypted |
48 | | } ETdDnodeEncryptStatus; |
49 | | |
50 | | // Encrypt file header structure (plaintext part at file beginning) |
51 | | typedef struct { |
52 | | char magic[TD_ENCRYPT_MAGIC_LEN]; // Magic number "tdEncrypt" |
53 | | int32_t algorithm; // Encryption algorithm (e.g., TSDB_ENCRYPT_ALGO_SM4 = 1) |
54 | | int32_t version; // File format version |
55 | | int32_t dataLen; // Length of encrypted data following header |
56 | | char reserved[32]; // Reserved for future use |
57 | | } STdEncryptFileHeader; |
58 | | |
59 | | // Encryption algorithm ID to name mapping |
60 | | // Based on EEncryptAlgo enum and mnode encryption algorithm definitions |
61 | | static const char *TD_ENCRYPT_ALGO_NAMES[] = { |
62 | | "NONE", // 0: ENCRYPT_ALGO_NONE |
63 | | "SM4-CBC:SM4", // 1: ENCRYPT_ALGO_SM4 / SM4 symmetric encryption |
64 | | "AES-128-CBC", // 2: AES symmetric encryption |
65 | | "SM3", // 3: ENCRYPT_ALGO_SM3 / SM3 digest |
66 | | "SHA-256", // 4: SHA-256 digest |
67 | | "SM2" // 5: ENCRYPT_ALGO_SM2 / SM2 asymmetric cipher |
68 | | }; |
69 | | |
70 | | #define TD_ENCRYPT_ALGO_NAME_MAX 6 |
71 | | |
72 | | // Get encryption algorithm name by ID |
73 | 0 | static inline const char *taosGetEncryptAlgoName(int32_t algorithm) { |
74 | 0 | if (algorithm >= 0 && algorithm < TD_ENCRYPT_ALGO_NAME_MAX) { |
75 | 0 | return TD_ENCRYPT_ALGO_NAMES[algorithm]; |
76 | 0 | } |
77 | 0 | return "UNKNOWN"; |
78 | 0 | } Unexecuted instantiation: tglobal.c:taosGetEncryptAlgoName Unexecuted instantiation: tencrypt.c:taosGetEncryptAlgoName |
79 | | |
80 | | /** |
81 | | * @brief Write file with encryption header using atomic file replacement |
82 | | * |
83 | | * This function writes data to a file with an encryption header at the beginning. |
84 | | * The caller is responsible for encrypting the data before passing it to this function. |
85 | | * It uses atomic file replacement strategy: writes to temp file, then renames. |
86 | | * |
87 | | * @param filepath Target file path |
88 | | * @param algorithm Encryption algorithm identifier (e.g., TSDB_ENCRYPT_ALGO_SM4) |
89 | | * @param data Data buffer to write (caller should encrypt data if needed, can be NULL for empty file) |
90 | | * @param dataLen Length of data to write (0 for empty file) |
91 | | * @return 0 on success, error code on failure |
92 | | */ |
93 | | int32_t taosWriteEncryptFileHeader(const char *filepath, int32_t algorithm, const void *data, int32_t dataLen); |
94 | | |
95 | | /** |
96 | | * @brief Read encryption header from file |
97 | | * |
98 | | * Reads and validates the encryption header from the beginning of a file. |
99 | | * |
100 | | * @param filepath File path to read |
101 | | * @param header Output parameter for header data |
102 | | * @return 0 on success, error code on failure |
103 | | */ |
104 | | int32_t taosReadEncryptFileHeader(const char *filepath, STdEncryptFileHeader *header); |
105 | | |
106 | | /** |
107 | | * @brief Check if file has encryption header |
108 | | * |
109 | | * Quickly checks if a file begins with the encryption magic number. |
110 | | * |
111 | | * @param filepath File path to check |
112 | | * @param algorithm Output parameter for algorithm (can be NULL) |
113 | | * @return true if file is encrypted, false otherwise |
114 | | */ |
115 | | bool taosIsEncryptedFile(const char *filepath, int32_t *algorithm); |
116 | | |
117 | | /** |
118 | | * @brief Write configuration file with encryption support |
119 | | * |
120 | | * Writes a configuration file with optional encryption based on tsCfgKey. |
121 | | * If tsCfgKey is enabled, encrypts the data using SM4 CBC algorithm and |
122 | | * writes it with an encryption header. Otherwise, writes the file normally. |
123 | | * |
124 | | * This function is used for transparent encryption of configuration files |
125 | | * including dnode.json, mnode.json, vnode.json, snode.json, raft_config.json, |
126 | | * raft_store.json, current.json, vnodes.json, and wal/meta-ver* files. |
127 | | * |
128 | | * @param filepath Target file path |
129 | | * @param data Data buffer to write |
130 | | * @param dataLen Length of data to write |
131 | | * @return 0 on success, error code on failure |
132 | | */ |
133 | | int32_t taosWriteCfgFile(const char *filepath, const void *data, int32_t dataLen); |
134 | | |
135 | | /** |
136 | | * @brief Read configuration file with automatic decryption support. |
137 | | * |
138 | | * This function reads a configuration file and automatically handles decryption if needed. |
139 | | * It checks if the file has an encryption header: |
140 | | * - If encrypted: reads header, reads encrypted data, decrypts using tsCfgKey |
141 | | * - If not encrypted: reads file content directly |
142 | | * |
143 | | * The caller is responsible for freeing the returned buffer. |
144 | | * |
145 | | * @param filepath File path to read |
146 | | * @param data Output parameter for data buffer (caller must free) |
147 | | * @param dataLen Output parameter for data length |
148 | | * @return 0 on success, error code on failure |
149 | | */ |
150 | | int32_t taosReadCfgFile(const char *filepath, char **data, int32_t *dataLen); |
151 | | |
152 | | /** |
153 | | * @brief Encrypt existing configuration files that are not yet encrypted. |
154 | | * |
155 | | * This function scans common configuration file locations and encrypts any |
156 | | * plaintext files it finds. It's called after encryption keys are loaded from mnode |
157 | | * to ensure all sensitive config files are encrypted. |
158 | | * |
159 | | * Files checked: |
160 | | * - dnode: dnode.info, dnode.json |
161 | | * - mnode: mnode.json, raft_config.json, raft_store.json |
162 | | * - vnode: vnodes.json |
163 | | * - snode: snode.json |
164 | | * |
165 | | * @param dataDir Data directory path (tsDataDir) |
166 | | * @return 0 on success, error code on failure |
167 | | */ |
168 | | int32_t taosEncryptExistingCfgFiles(const char *dataDir); |
169 | | |
170 | | /** |
171 | | * @brief Wait for encryption key to be loaded with timeout. |
172 | | * |
173 | | * This function checks if the CFG encryption key has been loaded successfully. |
174 | | * If the key is not yet loaded, it will loop and wait until either: |
175 | | * - The key is successfully loaded (returns 0) |
176 | | * - The timeout period expires (returns error code) |
177 | | * |
178 | | * The timeout is controlled by TD_ENCRYPT_KEY_WAIT_TIMEOUT_MS macro. |
179 | | * The check interval is 100ms between each attempt. |
180 | | * |
181 | | * @return 0 if key loaded successfully, TSDB_CODE_TIMEOUT_ERROR if timeout occurs |
182 | | */ |
183 | | int32_t taosWaitCfgKeyLoaded(void); |
184 | | |
185 | | #ifdef __cplusplus |
186 | | } |
187 | | #endif |
188 | | |
189 | | #endif /*_TD_COMMON_TENCRYPT_H_*/ |
190 | | |