Document of c-modernization-kit (porter) 1.0.0
Loading...
Searching...
No Matches
crypto_linux.c
Go to the documentation of this file.
1
19
20#ifndef _WIN32
21
22 #include <string.h>
23
24 #include <openssl/evp.h>
25
26 #include "crypto.h"
27
28/* doxygen コメントはヘッダに記載 */
29int potr_encrypt(uint8_t *dst, size_t *dst_len,
30 const uint8_t *src, size_t src_len,
31 const uint8_t *key,
32 const uint8_t *nonce,
33 const uint8_t *aad, size_t aad_len)
34{
35 EVP_CIPHER_CTX *ctx;
36 int outl;
37 int final_len;
38
39 if (dst == NULL || dst_len == NULL || (src == NULL && src_len > 0)
40 || key == NULL || nonce == NULL
41 || *dst_len < src_len + POTR_CRYPTO_TAG_SIZE)
42 {
43 return -1;
44 }
45
46 ctx = EVP_CIPHER_CTX_new();
47 if (ctx == NULL)
48 {
49 return -1;
50 }
51
52 if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1)
53 {
54 EVP_CIPHER_CTX_free(ctx);
55 return -1;
56 }
57
58 /* ノンス長を 12 バイトに設定 (デフォルトと同一だが明示する) */
59 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
60 (int)POTR_CRYPTO_NONCE_SIZE, NULL) != 1)
61 {
62 EVP_CIPHER_CTX_free(ctx);
63 return -1;
64 }
65
66 if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1)
67 {
68 EVP_CIPHER_CTX_free(ctx);
69 return -1;
70 }
71
72 /* AAD を入力 (ヘッダー改ざん検知用) */
73 if (aad != NULL && aad_len > 0)
74 {
75 if (EVP_EncryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1)
76 {
77 EVP_CIPHER_CTX_free(ctx);
78 return -1;
79 }
80 }
81
82 /* 平文を暗号化 (in-place 対応: dst == src 可)。平文 0B の場合はスキップ。 */
83 outl = 0;
84 if (src_len > 0)
85 {
86 if (EVP_EncryptUpdate(ctx, dst, &outl, src, (int)src_len) != 1)
87 {
88 EVP_CIPHER_CTX_free(ctx);
89 return -1;
90 }
91 }
92
93 /* GCM では EncryptFinal は追加データを出力しない (final_len == 0) */
94 if (EVP_EncryptFinal_ex(ctx, dst + outl, &final_len) != 1)
95 {
96 EVP_CIPHER_CTX_free(ctx);
97 return -1;
98 }
99
100 /* GCM 認証タグ (16 バイト) を暗号文の直後に書き込む */
101 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
103 dst + src_len) != 1)
104 {
105 EVP_CIPHER_CTX_free(ctx);
106 return -1;
107 }
108
109 *dst_len = src_len + POTR_CRYPTO_TAG_SIZE;
110
111 EVP_CIPHER_CTX_free(ctx);
112 return 0;
113}
114
115/* doxygen コメントはヘッダに記載 */
116int potr_decrypt(uint8_t *dst, size_t *dst_len,
117 const uint8_t *src, size_t src_len,
118 const uint8_t *key,
119 const uint8_t *nonce,
120 const uint8_t *aad, size_t aad_len){
121 EVP_CIPHER_CTX *ctx;
122 size_t plain_len;
123 int outl;
124 int final_len;
125
126 if (dst == NULL || dst_len == NULL || src == NULL
127 || src_len < POTR_CRYPTO_TAG_SIZE
128 || key == NULL || nonce == NULL)
129 {
130 return -1;
131 }
132
133 plain_len = src_len - POTR_CRYPTO_TAG_SIZE;
134
135 if (plain_len > 0 && *dst_len < plain_len)
136 {
137 return -1;
138 }
139
140 ctx = EVP_CIPHER_CTX_new();
141 if (ctx == NULL)
142 {
143 return -1;
144 }
145
146 if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1)
147 {
148 EVP_CIPHER_CTX_free(ctx);
149 return -1;
150 }
151
152 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
153 (int)POTR_CRYPTO_NONCE_SIZE, NULL) != 1)
154 {
155 EVP_CIPHER_CTX_free(ctx);
156 return -1;
157 }
158
159 if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce) != 1)
160 {
161 EVP_CIPHER_CTX_free(ctx);
162 return -1;
163 }
164
165 if (aad != NULL && aad_len > 0)
166 {
167 if (EVP_DecryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1)
168 {
169 EVP_CIPHER_CTX_free(ctx);
170 return -1;
171 }
172 }
173
174 /* 平文 0B の場合はスキップ */
175 outl = 0;
176 if (plain_len > 0)
177 {
178 if (EVP_DecryptUpdate(ctx, dst, &outl, src, (int)plain_len) != 1)
179 {
180 EVP_CIPHER_CTX_free(ctx);
181 return -1;
182 }
183 }
184
185 /* 認証タグを設定 (暗号文の末尾 POTR_CRYPTO_TAG_SIZE バイト)。
186 EVP_CIPHER_CTX_ctrl は void * を要求するため const を外すために
187 ローカルバッファにコピーしてから渡す (-Wcast-qual 回避)。 */
188 {
189 uint8_t tag_buf[POTR_CRYPTO_TAG_SIZE];
190 memcpy(tag_buf, src + plain_len, POTR_CRYPTO_TAG_SIZE);
191 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
192 (int)POTR_CRYPTO_TAG_SIZE, tag_buf) != 1)
193 {
194 EVP_CIPHER_CTX_free(ctx);
195 return -1;
196 }
197 }
198
199 /* DecryptFinal でタグ検証を行う。失敗時は -1 を返す。 */
200 if (EVP_DecryptFinal_ex(ctx, dst + outl, &final_len) != 1)
201 {
202 EVP_CIPHER_CTX_free(ctx);
203 return -1; /* 認証タグ不一致 */
204 }
205
206 *dst_len = plain_len;
207
208 EVP_CIPHER_CTX_free(ctx);
209 return 0;
210}
211
212/* doxygen コメントはヘッダに記載 */
213int potr_passphrase_to_key(uint8_t *key,
214 const uint8_t *passphrase,
215 size_t passphrase_len)
216{
217 EVP_MD_CTX *ctx;
218 unsigned int out_len = POTR_CRYPTO_KEY_SIZE;
219
220 if (key == NULL || (passphrase == NULL && passphrase_len > 0))
221 {
222 return -1;
223 }
224
225 ctx = EVP_MD_CTX_new();
226 if (ctx == NULL)
227 {
228 return -1;
229 }
230
231 if (EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) != 1
232 || EVP_DigestUpdate(ctx,
233 (passphrase != NULL) ? passphrase : (const uint8_t *)"",
234 passphrase_len) != 1
235 || EVP_DigestFinal_ex(ctx, key, &out_len) != 1)
236 {
237 EVP_MD_CTX_free(ctx);
238 return -1;
239 }
240
241 EVP_MD_CTX_free(ctx);
242 return 0;
243}
244
245#else /* _WIN32 */
246 #pragma warning(disable : 4206)
247#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 認証タグサイズ (バイト)。暗号文の直後に付加する。