/src/cryptsetup/lib/crypto_backend/argon2_generic.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: LGPL-2.1-or-later |
2 | | /* |
3 | | * Argon2 PBKDF2 library wrapper |
4 | | * |
5 | | * Copyright (C) 2016-2025 Red Hat, Inc. All rights reserved. |
6 | | * Copyright (C) 2016-2025 Milan Broz |
7 | | */ |
8 | | |
9 | | #include <errno.h> |
10 | | #include "crypto_backend_internal.h" |
11 | | |
12 | | /* Check for HAVE_ARGON2_H is run only if libargon2 code is used */ |
13 | | #if USE_INTERNAL_ARGON2 || HAVE_ARGON2_H |
14 | | |
15 | | #define CONST_CAST(x) (x)(uintptr_t) |
16 | | |
17 | | #if HAVE_ARGON2_H |
18 | | #include <argon2.h> |
19 | | #else |
20 | | #include "argon2/argon2.h" |
21 | | #endif |
22 | | |
23 | | int argon2(const char *type, const char *password, size_t password_length, |
24 | | const char *salt, size_t salt_length, |
25 | | char *key, size_t key_length, |
26 | | uint32_t iterations, uint32_t memory, uint32_t parallel) |
27 | | { |
28 | | argon2_type atype; |
29 | | argon2_context context = { |
30 | | .flags = ARGON2_DEFAULT_FLAGS, |
31 | | .version = ARGON2_VERSION_NUMBER, |
32 | | .t_cost = (uint32_t)iterations, |
33 | | .m_cost = (uint32_t)memory, |
34 | | .lanes = (uint32_t)parallel, |
35 | | .threads = (uint32_t)parallel, |
36 | | .out = (uint8_t *)key, |
37 | | .outlen = (uint32_t)key_length, |
38 | | .pwd = CONST_CAST(uint8_t *)password, |
39 | | .pwdlen = (uint32_t)password_length, |
40 | | .salt = CONST_CAST(uint8_t *)salt, |
41 | | .saltlen = (uint32_t)salt_length, |
42 | | }; |
43 | | int r; |
44 | | |
45 | | /* This code must not be run if crypt backend library natively supports Argon2 */ |
46 | | assert(!(crypt_backend_flags() & CRYPT_BACKEND_ARGON2)); |
47 | | |
48 | | if (!strcmp(type, "argon2i")) |
49 | | atype = Argon2_i; |
50 | | else if(!strcmp(type, "argon2id")) |
51 | | atype = Argon2_id; |
52 | | else |
53 | | return -EINVAL; |
54 | | |
55 | | switch (argon2_ctx(&context, atype)) { |
56 | | case ARGON2_OK: |
57 | | r = 0; |
58 | | break; |
59 | | case ARGON2_MEMORY_ALLOCATION_ERROR: |
60 | | case ARGON2_FREE_MEMORY_CBK_NULL: |
61 | | case ARGON2_ALLOCATE_MEMORY_CBK_NULL: |
62 | | r = -ENOMEM; |
63 | | break; |
64 | | default: |
65 | | r = -EINVAL; |
66 | | } |
67 | | |
68 | | return r; |
69 | | } |
70 | | |
71 | | #else /* USE_INTERNAL_ARGON2 || HAVE_ARGON2_H */ |
72 | | #pragma GCC diagnostic ignored "-Wunused-parameter" |
73 | | |
74 | | int argon2(const char *type, const char *password, size_t password_length, |
75 | | const char *salt, size_t salt_length, |
76 | | char *key, size_t key_length, |
77 | | uint32_t iterations, uint32_t memory, uint32_t parallel) |
78 | 0 | { |
79 | 0 | return -EINVAL; |
80 | 0 | } |
81 | | |
82 | | #endif |
83 | | |
84 | | /* Additional string for crypt backend version */ |
85 | | const char *crypt_argon2_version(void) |
86 | 3 | { |
87 | 3 | const char *version = ""; |
88 | | |
89 | 3 | if (crypt_backend_flags() & CRYPT_BACKEND_ARGON2) |
90 | 3 | return version; |
91 | | |
92 | | #if HAVE_ARGON2_H /* this has priority over internal argon2 */ |
93 | | version = " [external libargon2]"; |
94 | | #elif USE_INTERNAL_ARGON2 |
95 | | version = " [cryptsetup libargon2]"; |
96 | | #endif |
97 | 0 | return version; |
98 | 3 | } |