Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_digest.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
26
27#include "nilorea/n_digest.h"
28
29#ifdef HAVE_OPENSSL
30
31#include "nilorea/n_common.h"
32#include "nilorea/n_hex.h"
33#include "nilorea/n_log.h"
34#include "nilorea/n_str.h"
35
36#include <openssl/crypto.h>
37#include <openssl/evp.h>
38#include <openssl/hmac.h>
39
40#include <limits.h>
41#include <string.h>
42
43/* One-shot EVP digest shared by the public wrappers. A NULL data pointer is
44 * accepted only with len 0 (the digest of the empty input). */
45static int n_digest_oneshot(const EVP_MD* md, const unsigned char* data, size_t len, unsigned char* out, const char* name) {
46 if (!out || (!data && len > 0)) {
47 n_log(LOG_ERR, "n_digest_%s: invalid arguments", name);
48 return -1;
49 }
50 const unsigned char* in = data ? data : (const unsigned char*)"";
51 if (EVP_Digest(in, len, out, NULL, md, NULL) != 1) {
52 n_log(LOG_ERR, "n_digest_%s: EVP_Digest failed", name);
53 return -1;
54 }
55 return 0;
56}
57
58int n_digest_md5(const unsigned char* data, size_t len, unsigned char* out) {
59 return n_digest_oneshot(EVP_md5(), data, len, out, "md5");
60}
61
62int n_digest_sha1(const unsigned char* data, size_t len, unsigned char* out) {
63 return n_digest_oneshot(EVP_sha1(), data, len, out, "sha1");
64}
65
66int n_digest_sha256(const unsigned char* data, size_t len, unsigned char* out) {
67 return n_digest_oneshot(EVP_sha256(), data, len, out, "sha256");
68}
69
70int n_digest_sha384(const unsigned char* data, size_t len, unsigned char* out) {
71 return n_digest_oneshot(EVP_sha384(), data, len, out, "sha384");
72}
73
74int n_digest_sha512(const unsigned char* data, size_t len, unsigned char* out) {
75 return n_digest_oneshot(EVP_sha512(), data, len, out, "sha512");
76}
77
78/* BLAKE2b-512 reached OpenSSL in 1.1.0. Below that the digest simply is not in
79 the EVP table, so the entry point compiles to a logged failure and callers
80 still link; N_DIGEST_HAVE_BLAKE2B512 lets them skip the call instead. */
81#if N_DIGEST_HAVE_BLAKE2B512
82int n_digest_blake2b512(const unsigned char* data, size_t len, unsigned char* out) {
83 return n_digest_oneshot(EVP_blake2b512(), data, len, out, "blake2b512");
84}
85#else
86int n_digest_blake2b512(const unsigned char* data, size_t len, unsigned char* out) {
87 (void)data;
88 (void)len;
89 (void)out;
90 n_log(LOG_ERR, "n_digest_blake2b512: requires OpenSSL 1.1.0+ (EVP_blake2b512)");
91 return -1;
92}
93#endif
94
95N_STR* n_digest_sha256_hex(const unsigned char* data, size_t len) {
96 unsigned char md[N_DIGEST_SHA256_LEN];
97 if (n_digest_sha256(data, len, md) != 0) {
98 return NULL;
99 }
100 return n_hex_encode(md, sizeof(md));
101}
102
103/* Shared HMAC one-shot: compute HMAC(md) of data under key into out, validating
104 the produced length against the digest size. Returns 0 on success, -1 on error. */
105static int n_hmac_oneshot(const EVP_MD* md, unsigned int expect_len, const unsigned char* key, size_t key_len, const unsigned char* data, size_t data_len, unsigned char* out, const char* name) {
106 if (!out || (!key && key_len > 0) || (!data && data_len > 0)) {
107 n_log(LOG_ERR, "n_hmac_%s: invalid arguments", name);
108 return -1;
109 }
110 if (key_len > INT_MAX) {
111 n_log(LOG_ERR, "n_hmac_%s: key length %zu too large", name, key_len);
112 return -1;
113 }
114 const unsigned char* k = key ? key : (const unsigned char*)"";
115 const unsigned char* in = data ? data : (const unsigned char*)"";
116 unsigned int out_len = 0;
117 const unsigned char* r = HMAC(md, k, (int)key_len, in, data_len, out, &out_len);
118 if (!r || out_len != expect_len) {
119 n_log(LOG_ERR, "n_hmac_%s: HMAC failed (out_len %u)", name, out_len);
120 return -1;
121 }
122 return 0;
123}
124
125int n_hmac_sha1(const unsigned char* key, size_t key_len, const unsigned char* data, size_t data_len, unsigned char* out) {
126 return n_hmac_oneshot(EVP_sha1(), N_DIGEST_SHA1_LEN, key, key_len, data, data_len, out, "sha1");
127}
128
129int n_hmac_sha256(const unsigned char* key, size_t key_len, const unsigned char* data, size_t data_len, unsigned char* out) {
130 return n_hmac_oneshot(EVP_sha256(), N_DIGEST_SHA256_LEN, key, key_len, data, data_len, out, "sha256");
131}
132
133int n_hmac_sha384(const unsigned char* key, size_t key_len, const unsigned char* data, size_t data_len, unsigned char* out) {
134 return n_hmac_oneshot(EVP_sha384(), N_DIGEST_SHA384_LEN, key, key_len, data, data_len, out, "sha384");
135}
136
137int n_hmac_sha512(const unsigned char* key, size_t key_len, const unsigned char* data, size_t data_len, unsigned char* out) {
138 return n_hmac_oneshot(EVP_sha512(), N_DIGEST_SHA512_LEN, key, key_len, data, data_len, out, "sha512");
139}
140
141int n_digest_consttime_equal(const unsigned char* a, const unsigned char* b, size_t len) {
142 if (!a || !b)
143 return 0;
144 return CRYPTO_memcmp(a, b, len) == 0 ? 1 : 0;
145}
146
147/* Shared PBKDF2 one-shot over the OpenSSL PKCS5 API, validating argument ranges. */
148static int n_pbkdf2_oneshot(const EVP_MD* md, const unsigned char* pass, size_t pass_len, const unsigned char* salt, size_t salt_len, unsigned int iterations, unsigned char* out, size_t out_len, const char* name) {
149 if (!out || out_len == 0 || iterations == 0 || (!pass && pass_len > 0) || (!salt && salt_len > 0)) {
150 n_log(LOG_ERR, "n_pbkdf2_%s: invalid arguments", name);
151 return -1;
152 }
153 if (pass_len > INT_MAX || salt_len > INT_MAX || out_len > INT_MAX || iterations > (unsigned int)INT_MAX) {
154 n_log(LOG_ERR, "n_pbkdf2_%s: argument too large", name);
155 return -1;
156 }
157 const char* p = pass ? (const char*)pass : "";
158 const unsigned char* s = salt ? salt : (const unsigned char*)"";
159 if (PKCS5_PBKDF2_HMAC(p, (int)pass_len, s, (int)salt_len, (int)iterations, md, (int)out_len, out) != 1) {
160 n_log(LOG_ERR, "n_pbkdf2_%s: PKCS5_PBKDF2_HMAC failed", name);
161 return -1;
162 }
163 return 0;
164}
165
166int n_pbkdf2_hmac_sha1(const unsigned char* pass, size_t pass_len, const unsigned char* salt, size_t salt_len, unsigned int iterations, unsigned char* out, size_t out_len) {
167 return n_pbkdf2_oneshot(EVP_sha1(), pass, pass_len, salt, salt_len, iterations, out, out_len, "sha1");
168}
169
170int n_pbkdf2_hmac_sha256(const unsigned char* pass, size_t pass_len, const unsigned char* salt, size_t salt_len, unsigned int iterations, unsigned char* out, size_t out_len) {
171 return n_pbkdf2_oneshot(EVP_sha256(), pass, pass_len, salt, salt_len, iterations, out, out_len, "sha256");
172}
173
174int n_aead_aes256gcm_encrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* pt, size_t pt_len, unsigned char* out_ct, unsigned char* out_tag) {
175 EVP_CIPHER_CTX* ctx;
176 int outl = 0;
177 int rc = -1;
178 if (!key || !iv || iv_len == 0 || !out_ct || !out_tag || (!pt && pt_len > 0) || (!aad && aad_len > 0) || iv_len > INT_MAX || pt_len > INT_MAX || aad_len > INT_MAX) {
179 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: invalid arguments");
180 return -1;
181 }
182 ctx = EVP_CIPHER_CTX_new();
183 if (!ctx) {
184 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: EVP_CIPHER_CTX_new failed");
185 return -1;
186 }
187 if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1 ||
188 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv_len, NULL) != 1 ||
189 EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
190 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: init failed");
191 goto end;
192 }
193 if (aad_len > 0 && EVP_EncryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1) {
194 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: AAD failed");
195 goto end;
196 }
197 if (pt_len > 0 && EVP_EncryptUpdate(ctx, out_ct, &outl, pt, (int)pt_len) != 1) {
198 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: encrypt failed");
199 goto end;
200 }
201 if (EVP_EncryptFinal_ex(ctx, out_ct + outl, &outl) != 1 ||
202 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, N_AEAD_AES256GCM_TAG_LEN, out_tag) != 1) {
203 n_log(LOG_ERR, "n_aead_aes256gcm_encrypt: finalize failed");
204 goto end;
205 }
206 rc = 0;
207end:
208 EVP_CIPHER_CTX_free(ctx);
209 return rc;
210}
211
212int n_aead_aes256gcm_decrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* ct, size_t ct_len, const unsigned char* tag, unsigned char* out_pt) {
213 EVP_CIPHER_CTX* ctx;
214 unsigned char tagbuf[N_AEAD_AES256GCM_TAG_LEN];
215 int outl = 0;
216 int rc = -1;
217 if (!key || !iv || iv_len == 0 || !tag || !out_pt || (!ct && ct_len > 0) || (!aad && aad_len > 0) || iv_len > INT_MAX || ct_len > INT_MAX || aad_len > INT_MAX) {
218 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: invalid arguments");
219 return -1;
220 }
221 ctx = EVP_CIPHER_CTX_new();
222 if (!ctx) {
223 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: EVP_CIPHER_CTX_new failed");
224 return -1;
225 }
226 if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1 ||
227 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv_len, NULL) != 1 ||
228 EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
229 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: init failed");
230 goto end;
231 }
232 if (aad_len > 0 && EVP_DecryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1) {
233 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: AAD failed");
234 goto end;
235 }
236 if (ct_len > 0 && EVP_DecryptUpdate(ctx, out_pt, &outl, ct, (int)ct_len) != 1) {
237 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: decrypt failed");
238 goto end;
239 }
240 memcpy(tagbuf, tag, N_AEAD_AES256GCM_TAG_LEN); /* SET_TAG wants a non-const buffer */
241 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, N_AEAD_AES256GCM_TAG_LEN, tagbuf) != 1) {
242 n_log(LOG_ERR, "n_aead_aes256gcm_decrypt: set tag failed");
243 goto end;
244 }
245 /* EVP_DecryptFinal_ex returns >0 only when the authentication tag verifies */
246 if (EVP_DecryptFinal_ex(ctx, out_pt + outl, &outl) > 0)
247 rc = 0;
248end:
249 EVP_CIPHER_CTX_free(ctx);
250 return rc;
251}
252
253/* ChaCha20-Poly1305 and the EVP_CTRL_AEAD_* control names both arrived in
254 OpenSSL 1.1.0. Below that the pair compiles to logged failures rather than
255 dropping out of the ABI, so a program built against a newer OpenSSL and one
256 built against 1.0.2 expose the same symbols; N_AEAD_HAVE_CHACHA20POLY1305
257 tells a caller which of the two it linked. AES-256-GCM above is unaffected,
258 it is spelled with the EVP_CTRL_GCM_* names 1.0.2 already has. */
259#if N_AEAD_HAVE_CHACHA20POLY1305
260int n_aead_chacha20poly1305_encrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* pt, size_t pt_len, unsigned char* out_ct, unsigned char* out_tag) {
261 EVP_CIPHER_CTX* ctx;
262 int outl = 0;
263 int rc = -1;
264 if (!key || !iv || iv_len == 0 || !out_ct || !out_tag || (!pt && pt_len > 0) || (!aad && aad_len > 0) || iv_len > INT_MAX || pt_len > INT_MAX || aad_len > INT_MAX) {
265 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: invalid arguments");
266 return -1;
267 }
268 ctx = EVP_CIPHER_CTX_new();
269 if (!ctx) {
270 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: EVP_CIPHER_CTX_new failed");
271 return -1;
272 }
273 if (EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL) != 1 ||
274 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, (int)iv_len, NULL) != 1 ||
275 EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
276 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: init failed");
277 goto end;
278 }
279 if (aad_len > 0 && EVP_EncryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1) {
280 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: AAD failed");
281 goto end;
282 }
283 if (pt_len > 0 && EVP_EncryptUpdate(ctx, out_ct, &outl, pt, (int)pt_len) != 1) {
284 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: encrypt failed");
285 goto end;
286 }
287 if (EVP_EncryptFinal_ex(ctx, out_ct + outl, &outl) != 1 ||
288 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, N_AEAD_CHACHA20POLY1305_TAG_LEN, out_tag) != 1) {
289 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: finalize failed");
290 goto end;
291 }
292 rc = 0;
293end:
294 EVP_CIPHER_CTX_free(ctx);
295 return rc;
296}
297
298int n_aead_chacha20poly1305_decrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* ct, size_t ct_len, const unsigned char* tag, unsigned char* out_pt) {
299 EVP_CIPHER_CTX* ctx;
300 unsigned char tagbuf[N_AEAD_CHACHA20POLY1305_TAG_LEN];
301 int outl = 0;
302 int rc = -1;
303 if (!key || !iv || iv_len == 0 || !tag || !out_pt || (!ct && ct_len > 0) || (!aad && aad_len > 0) || iv_len > INT_MAX || ct_len > INT_MAX || aad_len > INT_MAX) {
304 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: invalid arguments");
305 return -1;
306 }
307 ctx = EVP_CIPHER_CTX_new();
308 if (!ctx) {
309 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: EVP_CIPHER_CTX_new failed");
310 return -1;
311 }
312 if (EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL) != 1 ||
313 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, (int)iv_len, NULL) != 1 ||
314 EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
315 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: init failed");
316 goto end;
317 }
318 if (aad_len > 0 && EVP_DecryptUpdate(ctx, NULL, &outl, aad, (int)aad_len) != 1) {
319 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: AAD failed");
320 goto end;
321 }
322 if (ct_len > 0 && EVP_DecryptUpdate(ctx, out_pt, &outl, ct, (int)ct_len) != 1) {
323 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: decrypt failed");
324 goto end;
325 }
326 memcpy(tagbuf, tag, N_AEAD_CHACHA20POLY1305_TAG_LEN); /* SET_TAG wants a non-const buffer */
327 if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, N_AEAD_CHACHA20POLY1305_TAG_LEN, tagbuf) != 1) {
328 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: set tag failed");
329 goto end;
330 }
331 /* EVP_DecryptFinal_ex returns >0 only when the authentication tag verifies */
332 if (EVP_DecryptFinal_ex(ctx, out_pt + outl, &outl) > 0)
333 rc = 0;
334end:
335 EVP_CIPHER_CTX_free(ctx);
336 return rc;
337}
338#else
339int n_aead_chacha20poly1305_encrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* pt, size_t pt_len, unsigned char* out_ct, unsigned char* out_tag) {
340 (void)key;
341 (void)iv;
342 (void)iv_len;
343 (void)aad;
344 (void)aad_len;
345 (void)pt;
346 (void)pt_len;
347 (void)out_ct;
348 (void)out_tag;
349 n_log(LOG_ERR, "n_aead_chacha20poly1305_encrypt: requires OpenSSL 1.1.0+ (EVP_chacha20_poly1305)");
350 return -1;
351}
352
353int n_aead_chacha20poly1305_decrypt(const unsigned char* key, const unsigned char* iv, size_t iv_len, const unsigned char* aad, size_t aad_len, const unsigned char* ct, size_t ct_len, const unsigned char* tag, unsigned char* out_pt) {
354 (void)key;
355 (void)iv;
356 (void)iv_len;
357 (void)aad;
358 (void)aad_len;
359 (void)ct;
360 (void)ct_len;
361 (void)tag;
362 (void)out_pt;
363 n_log(LOG_ERR, "n_aead_chacha20poly1305_decrypt: requires OpenSSL 1.1.0+ (EVP_chacha20_poly1305)");
364 return -1;
365}
366#endif
367
368/* HKDF and scrypt use the OpenSSL 3.0 provider KDF API (EVP_KDF); on older
369 OpenSSL they compile to a logged failure so callers still link. */
370#if N_KDF_HAVE_EVP_KDF
371#include <openssl/core_names.h>
372#include <openssl/kdf.h>
373#include <openssl/params.h>
374
375int n_kdf_hkdf_sha256(const unsigned char* ikm, size_t ikm_len, const unsigned char* salt, size_t salt_len, const unsigned char* info, size_t info_len, unsigned char* out, size_t out_len) {
376 if (!out || out_len == 0 || (!ikm && ikm_len > 0) || (!salt && salt_len > 0) || (!info && info_len > 0)) {
377 n_log(LOG_ERR, "n_kdf_hkdf_sha256: invalid arguments");
378 return -1;
379 }
380 int rc = -1;
381 EVP_KDF* kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
382 EVP_KDF_CTX* kctx = NULL;
383 OSSL_PARAM params[5];
384 size_t i = 0;
385 char digest[] = "SHA256";
386 if (!kdf) {
387 n_log(LOG_ERR, "n_kdf_hkdf_sha256: EVP_KDF_fetch(HKDF) failed");
388 goto done;
389 }
390 kctx = EVP_KDF_CTX_new(kdf);
391 if (!kctx) goto done;
392 params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, digest, 0);
393 params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void*)ikm, ikm_len);
394 params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void*)salt, salt_len);
395 params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void*)info, info_len);
396 params[i] = OSSL_PARAM_construct_end();
397 if (EVP_KDF_derive(kctx, out, out_len, params) == 1)
398 rc = 0;
399 else
400 n_log(LOG_ERR, "n_kdf_hkdf_sha256: EVP_KDF_derive failed");
401done:
402 EVP_KDF_CTX_free(kctx);
403 EVP_KDF_free(kdf);
404 return rc;
405}
406
407int n_kdf_scrypt(const unsigned char* pass, size_t pass_len, const unsigned char* salt, size_t salt_len, uint64_t n, uint32_t r, uint32_t p, uint64_t maxmem, unsigned char* out, size_t out_len) {
408 if (!out || out_len == 0 || (!pass && pass_len > 0) || (!salt && salt_len > 0)) {
409 n_log(LOG_ERR, "n_kdf_scrypt: invalid arguments");
410 return -1;
411 }
412 int rc = -1;
413 EVP_KDF* kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
414 EVP_KDF_CTX* kctx = NULL;
415 OSSL_PARAM params[7];
416 size_t i = 0;
417 if (!kdf) {
418 n_log(LOG_ERR, "n_kdf_scrypt: EVP_KDF_fetch(SCRYPT) failed");
419 goto done;
420 }
421 kctx = EVP_KDF_CTX_new(kdf);
422 if (!kctx) goto done;
423 params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, (void*)pass, pass_len);
424 params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (void*)salt, salt_len);
425 params[i++] = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_N, &n);
426 params[i++] = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_R, &r);
427 params[i++] = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_P, &p);
428 params[i++] = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, &maxmem);
429 params[i] = OSSL_PARAM_construct_end();
430 if (EVP_KDF_derive(kctx, out, out_len, params) == 1)
431 rc = 0;
432 else
433 n_log(LOG_ERR, "n_kdf_scrypt: EVP_KDF_derive failed");
434done:
435 EVP_KDF_CTX_free(kctx);
436 EVP_KDF_free(kdf);
437 return rc;
438}
439#else
440int n_kdf_hkdf_sha256(const unsigned char* ikm, size_t ikm_len, const unsigned char* salt, size_t salt_len, const unsigned char* info, size_t info_len, unsigned char* out, size_t out_len) {
441 (void)ikm;
442 (void)ikm_len;
443 (void)salt;
444 (void)salt_len;
445 (void)info;
446 (void)info_len;
447 (void)out;
448 (void)out_len;
449 n_log(LOG_ERR, "n_kdf_hkdf_sha256: requires OpenSSL 3.0+ (EVP_KDF)");
450 return -1;
451}
452int n_kdf_scrypt(const unsigned char* pass, size_t pass_len, const unsigned char* salt, size_t salt_len, uint64_t n, uint32_t r, uint32_t p, uint64_t maxmem, unsigned char* out, size_t out_len) {
453 (void)pass;
454 (void)pass_len;
455 (void)salt;
456 (void)salt_len;
457 (void)n;
458 (void)r;
459 (void)p;
460 (void)maxmem;
461 (void)out;
462 (void)out_len;
463 n_log(LOG_ERR, "n_kdf_scrypt: requires OpenSSL 3.0+ (EVP_KDF)");
464 return -1;
465}
466#endif
467
468#endif /* HAVE_OPENSSL */
volatile sig_atomic_t done
volatile char key[227]
TRUE while the key is held.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
int n_digest_sha256(const unsigned char *data, size_t len, unsigned char *out)
compute the SHA-256 digest of len bytes of data into out (N_DIGEST_SHA256_LEN bytes).
Definition n_digest.c:66
int n_kdf_scrypt(const unsigned char *pass, size_t pass_len, const unsigned char *salt, size_t salt_len, uint64_t n, uint32_t r, uint32_t p, uint64_t maxmem, unsigned char *out, size_t out_len)
scrypt (RFC 7914) of pass with salt and cost parameters n (CPU/memory, a power of two),...
Definition n_digest.c:452
#define N_DIGEST_SHA512_LEN
output size in bytes of a SHA-512 digest
Definition n_digest.h:73
int n_aead_chacha20poly1305_encrypt(const unsigned char *key, const unsigned char *iv, size_t iv_len, const unsigned char *aad, size_t aad_len, const unsigned char *pt, size_t pt_len, unsigned char *out_ct, unsigned char *out_tag)
ChaCha20-Poly1305 (RFC 8439) authenticated encryption.
Definition n_digest.c:339
int n_digest_sha512(const unsigned char *data, size_t len, unsigned char *out)
compute the SHA-512 digest of len bytes of data into out (N_DIGEST_SHA512_LEN bytes).
Definition n_digest.c:74
int n_kdf_hkdf_sha256(const unsigned char *ikm, size_t ikm_len, const unsigned char *salt, size_t salt_len, const unsigned char *info, size_t info_len, unsigned char *out, size_t out_len)
HKDF-SHA256 (RFC 5869 extract-then-expand) of ikm with the given salt and info into out (out_len byte...
Definition n_digest.c:440
int n_pbkdf2_hmac_sha1(const unsigned char *pass, size_t pass_len, const unsigned char *salt, size_t salt_len, unsigned int iterations, unsigned char *out, size_t out_len)
derive out_len key bytes from pass and salt with PBKDF2-HMAC-SHA1 over iterations rounds (RFC 2898).
Definition n_digest.c:166
#define N_DIGEST_SHA384_LEN
output size in bytes of a SHA-384 digest
Definition n_digest.h:71
int n_hmac_sha256(const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len, unsigned char *out)
compute HMAC-SHA256 of data under key into out (N_DIGEST_SHA256_LEN bytes).
Definition n_digest.c:129
#define N_AEAD_AES256GCM_TAG_LEN
authentication tag size in bytes for AES-256-GCM
Definition n_digest.h:113
#define N_AEAD_CHACHA20POLY1305_TAG_LEN
authentication tag size in bytes for ChaCha20-Poly1305
Definition n_digest.h:123
int n_aead_aes256gcm_encrypt(const unsigned char *key, const unsigned char *iv, size_t iv_len, const unsigned char *aad, size_t aad_len, const unsigned char *pt, size_t pt_len, unsigned char *out_ct, unsigned char *out_tag)
AES-256-GCM authenticated encryption.
Definition n_digest.c:174
#define N_DIGEST_SHA256_LEN
output size in bytes of a SHA-256 digest
Definition n_digest.h:69
int n_hmac_sha1(const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len, unsigned char *out)
compute HMAC-SHA1 of data under key into out (N_DIGEST_SHA1_LEN bytes).
Definition n_digest.c:125
int n_digest_sha1(const unsigned char *data, size_t len, unsigned char *out)
compute the SHA-1 digest of len bytes of data into out (N_DIGEST_SHA1_LEN bytes).
Definition n_digest.c:62
#define N_DIGEST_SHA1_LEN
output size in bytes of a SHA-1 digest
Definition n_digest.h:67
int n_pbkdf2_hmac_sha256(const unsigned char *pass, size_t pass_len, const unsigned char *salt, size_t salt_len, unsigned int iterations, unsigned char *out, size_t out_len)
derive out_len key bytes from pass and salt with PBKDF2-HMAC-SHA256 over iterations rounds (RFC 2898)...
Definition n_digest.c:170
int n_digest_consttime_equal(const unsigned char *a, const unsigned char *b, size_t len)
constant-time comparison of two equal-length byte buffers (for verifying MACs/signatures without a ti...
Definition n_digest.c:141
int n_hmac_sha512(const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len, unsigned char *out)
compute HMAC-SHA512 of data under key into out (N_DIGEST_SHA512_LEN bytes).
Definition n_digest.c:137
int n_digest_sha384(const unsigned char *data, size_t len, unsigned char *out)
compute the SHA-384 digest of len bytes of data into out (N_DIGEST_SHA384_LEN bytes).
Definition n_digest.c:70
int n_hmac_sha384(const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len, unsigned char *out)
compute HMAC-SHA384 of data under key into out (N_DIGEST_SHA384_LEN bytes).
Definition n_digest.c:133
int n_aead_aes256gcm_decrypt(const unsigned char *key, const unsigned char *iv, size_t iv_len, const unsigned char *aad, size_t aad_len, const unsigned char *ct, size_t ct_len, const unsigned char *tag, unsigned char *out_pt)
AES-256-GCM authenticated decryption.
Definition n_digest.c:212
int n_digest_md5(const unsigned char *data, size_t len, unsigned char *out)
compute the MD5 digest of len bytes of data into out (N_DIGEST_MD5_LEN bytes).
Definition n_digest.c:58
int n_aead_chacha20poly1305_decrypt(const unsigned char *key, const unsigned char *iv, size_t iv_len, const unsigned char *aad, size_t aad_len, const unsigned char *ct, size_t ct_len, const unsigned char *tag, unsigned char *out_pt)
ChaCha20-Poly1305 authenticated decryption.
Definition n_digest.c:353
N_STR * n_digest_sha256_hex(const unsigned char *data, size_t len)
compute the SHA-256 digest of data and return it as a lowercase hex N_STR; free with free_nstr.
Definition n_digest.c:95
int n_digest_blake2b512(const unsigned char *data, size_t len, unsigned char *out)
compute the BLAKE2b-512 digest of len bytes of data into out (N_DIGEST_BLAKE2B512_LEN bytes).
Definition n_digest.c:86
N_STR * n_hex_encode(const unsigned char *data, size_t len)
encode len bytes of data as a lowercase hex N_STR (2*len characters); free with free_nstr.
Definition n_hex.c:48
A box including a string and his lenght.
Definition n_str.h:61
Common headers and low-level functions & define.
static int n_hmac_oneshot(const EVP_MD *md, unsigned int expect_len, const unsigned char *key, size_t key_len, const unsigned char *data, size_t data_len, unsigned char *out, const char *name)
Definition n_digest.c:105
static int n_digest_oneshot(const EVP_MD *md, const unsigned char *data, size_t len, unsigned char *out, const char *name)
Definition n_digest.c:45
static int n_pbkdf2_oneshot(const EVP_MD *md, const unsigned char *pass, size_t pass_len, const unsigned char *salt, size_t salt_len, unsigned int iterations, unsigned char *out, size_t out_len, const char *name)
Definition n_digest.c:148
Message digests, HMAC, PBKDF2, and AES-256-GCM AEAD over the OpenSSL EVP API.
Hexadecimal encode/decode helpers.
Generic log system.
N_STR and string function declaration.