Document of c-modernization-kit (porter) 1.0.0
Loading...
Searching...
No Matches
crypto_windows.c
Go to the documentation of this file.
1
20
21#ifdef _WIN32
22
23 #include <windows.h>
24 #include <bcrypt.h>
25 #include <string.h>
26
27 #include "crypto.h"
28
29/* BCrypt を使用した AES-256-GCM 暗号化の共通実装。
30 is_encrypt: TRUE = 暗号化、FALSE = 復号 (タグ検証含む)。
31 src/src_len: 暗号化時は平文、復号時は暗号文 (タグを除く)。
32 tag: 暗号化時は出力バッファ、復号時は検証用入力バッファ。 */
33static int bcrypt_aes_gcm(BOOL is_encrypt,
34 uint8_t *dst,
35 size_t *dst_len,
36 const uint8_t *src,
37 size_t src_len,
38 const uint8_t *key,
39 const uint8_t *nonce,
40 const uint8_t *aad,
41 size_t aad_len,
42 uint8_t *tag,
43 ULONG tag_len)
44{
45 BCRYPT_ALG_HANDLE h_alg = NULL;
46 BCRYPT_KEY_HANDLE h_key = NULL;
47 NTSTATUS status;
48 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info;
49 ULONG out_len = 0;
50
51 status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_AES_ALGORITHM, NULL, 0);
52 if (!BCRYPT_SUCCESS(status))
53 {
54 return -1;
55 }
56
57 status = BCryptSetProperty(h_alg, BCRYPT_CHAINING_MODE,
58 (PUCHAR)BCRYPT_CHAIN_MODE_GCM,
59 sizeof(BCRYPT_CHAIN_MODE_GCM), 0);
60 if (!BCRYPT_SUCCESS(status))
61 {
62 BCryptCloseAlgorithmProvider(h_alg, 0);
63 return -1;
64 }
65
66 status = BCryptGenerateSymmetricKey(h_alg, &h_key, NULL, 0,
67 (PUCHAR)key, (ULONG)POTR_CRYPTO_KEY_SIZE, 0);
68 if (!BCRYPT_SUCCESS(status))
69 {
70 BCryptCloseAlgorithmProvider(h_alg, 0);
71 return -1;
72 }
73
74 BCRYPT_INIT_AUTH_MODE_INFO(auth_info);
75 auth_info.pbNonce = (PUCHAR)nonce;
76 auth_info.cbNonce = (ULONG)POTR_CRYPTO_NONCE_SIZE;
77 auth_info.pbAuthData = (PUCHAR)aad;
78 auth_info.cbAuthData = (aad != NULL) ? (ULONG)aad_len : 0U;
79 auth_info.pbTag = (PUCHAR)tag;
80 auth_info.cbTag = tag_len;
81
82 if (is_encrypt)
83 {
84 status = BCryptEncrypt(h_key,
85 (PUCHAR)src, (ULONG)src_len,
86 &auth_info,
87 NULL, 0,
88 (PUCHAR)dst, (ULONG)*dst_len,
89 &out_len, 0);
90 }
91 else
92 {
93 status = BCryptDecrypt(h_key,
94 (PUCHAR)src, (ULONG)src_len,
95 &auth_info,
96 NULL, 0,
97 (PUCHAR)dst, (ULONG)*dst_len,
98 &out_len, 0);
99 }
100
101 BCryptDestroyKey(h_key);
102 BCryptCloseAlgorithmProvider(h_alg, 0);
103
104 if (!BCRYPT_SUCCESS(status))
105 {
106 return -1;
107 }
108
109 *dst_len = (size_t)out_len;
110 return 0;
111}
112
113/* doxygen コメントはヘッダに記載 */
114int potr_encrypt(uint8_t *dst, size_t *dst_len,
115 const uint8_t *src, size_t src_len,
116 const uint8_t *key,
117 const uint8_t *nonce,
118 const uint8_t *aad, size_t aad_len)
119{
120 uint8_t tag[POTR_CRYPTO_TAG_SIZE];
121 size_t enc_len;
122
123 if (dst == NULL || dst_len == NULL || (src == NULL && src_len > 0)
124 || key == NULL || nonce == NULL
125 || *dst_len < src_len + POTR_CRYPTO_TAG_SIZE)
126 {
127 return -1;
128 }
129
130 enc_len = src_len;
131
132 {
133 /* BCrypt は src=NULL を受け付けないため、空バッファを用意する */
134 static const uint8_t empty_src[1] = { 0 };
135 const uint8_t *actual_src = (src != NULL) ? src : empty_src;
136
137 if (bcrypt_aes_gcm(TRUE,
138 dst, &enc_len,
139 actual_src, src_len,
140 key, nonce,
141 aad, aad_len,
142 tag, (ULONG)POTR_CRYPTO_TAG_SIZE) != 0)
143 {
144 return -1;
145 }
146 }
147
148 /* タグ (16B) を暗号文の直後に付加する */
149 memcpy(dst + enc_len, tag, POTR_CRYPTO_TAG_SIZE);
150 *dst_len = enc_len + POTR_CRYPTO_TAG_SIZE;
151 return 0;
152}
153
154/* doxygen コメントはヘッダに記載 */
155int potr_decrypt(uint8_t *dst, size_t *dst_len,
156 const uint8_t *src, size_t src_len,
157 const uint8_t *key,
158 const uint8_t *nonce,
159 const uint8_t *aad, size_t aad_len)
160{
161 size_t plain_len;
162
163 if (dst == NULL || dst_len == NULL || src == NULL
164 || src_len < POTR_CRYPTO_TAG_SIZE
165 || key == NULL || nonce == NULL)
166 {
167 return -1;
168 }
169
170 plain_len = src_len - POTR_CRYPTO_TAG_SIZE;
171
172 if (plain_len > 0 && *dst_len < plain_len)
173 {
174 return -1;
175 }
176
177 /* タグは暗号文の末尾 POTR_CRYPTO_TAG_SIZE バイト。BCrypt がタグ検証を行う。
178 STATUS_AUTH_TAG_MISMATCH 時は bcrypt_aes_gcm が -1 を返す。 */
179 return bcrypt_aes_gcm(FALSE,
180 dst, dst_len,
181 src, plain_len,
182 key, nonce,
183 aad, aad_len,
184 (uint8_t *)(src + plain_len),
185 (ULONG)POTR_CRYPTO_TAG_SIZE);
186}
187
188/* doxygen コメントはヘッダに記載 */
189int potr_passphrase_to_key(uint8_t *key,
190 const uint8_t *passphrase,
191 size_t passphrase_len)
192{
193 BCRYPT_ALG_HANDLE h_alg = NULL;
194 BCRYPT_HASH_HANDLE h_hash = NULL;
195 NTSTATUS status;
196 static const uint8_t empty[1] = { 0 };
197 const uint8_t *data = (passphrase != NULL) ? passphrase : empty;
198 ULONG data_len = (passphrase != NULL) ? (ULONG)passphrase_len : 0UL;
199
200 if (key == NULL || (passphrase == NULL && passphrase_len > 0))
201 {
202 return -1;
203 }
204
205 status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_SHA256_ALGORITHM, NULL, 0);
206 if (!BCRYPT_SUCCESS(status))
207 {
208 return -1;
209 }
210
211 status = BCryptCreateHash(h_alg, &h_hash, NULL, 0, NULL, 0, 0);
212 if (!BCRYPT_SUCCESS(status))
213 {
214 BCryptCloseAlgorithmProvider(h_alg, 0);
215 return -1;
216 }
217
218 status = BCryptHashData(h_hash, (PUCHAR)data, data_len, 0);
219 if (!BCRYPT_SUCCESS(status))
220 {
221 BCryptDestroyHash(h_hash);
222 BCryptCloseAlgorithmProvider(h_alg, 0);
223 return -1;
224 }
225
226 status = BCryptFinishHash(h_hash, (PUCHAR)key, (ULONG)POTR_CRYPTO_KEY_SIZE, 0);
227
228 BCryptDestroyHash(h_hash);
229 BCryptCloseAlgorithmProvider(h_alg, 0);
230
231 return BCRYPT_SUCCESS(status) ? 0 : -1;
232}
233
234#endif /* _WIN32 */
データ暗号化・復号モジュールの内部ヘッダー。
int potr_passphrase_to_key(uint8_t *key, const uint8_t *passphrase, size_t passphrase_len)
任意のパスフレーズを SHA-256 ハッシュにより AES-256 鍵に変換します。
int potr_encrypt(uint8_t *dst, size_t *dst_len, const uint8_t *src, size_t src_len, const uint8_t *key, const uint8_t *nonce, const uint8_t *aad, size_t aad_len)
AES-256-GCM でデータを暗号化します。
int potr_decrypt(uint8_t *dst, size_t *dst_len, const uint8_t *src, size_t src_len, const uint8_t *key, const uint8_t *nonce, const uint8_t *aad, size_t aad_len)
AES-256-GCM でデータを復号し、認証タグを検証します。
#define POTR_CRYPTO_NONCE_SIZE
AES-256-GCM ノンスサイズ (バイト)。session_id (4B NBO) + flags (2B NBO) + seq_or_ack_num (4B NBO) + padding (2B...
#define POTR_CRYPTO_KEY_SIZE
AES-256-GCM 鍵サイズ (バイト)。設定ファイルの encrypt_key に 64 文字 hex で指定する。
#define POTR_CRYPTO_TAG_SIZE
AES-256-GCM 認証タグサイズ (バイト)。暗号文の直後に付加する。