64cf10bd1700e6c959a982c136e07b4fd7aaa67f
[platform/upstream/cryptsetup.git] / lib / crypto_backend / argon2_generic.c
1 /*
2  * Argon2 PBKDF2 library wrapper
3  *
4  * Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2016-2020 Milan Broz
6  *
7  * This file is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this file; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <errno.h>
23 #include "crypto_backend_internal.h"
24 #if HAVE_ARGON2_H
25 #include <argon2.h>
26 #else
27 #include "argon2/argon2.h"
28 #endif
29
30 #define CONST_CAST(x) (x)(uintptr_t)
31
32 int argon2(const char *type, const char *password, size_t password_length,
33            const char *salt, size_t salt_length,
34            char *key, size_t key_length,
35            uint32_t iterations, uint32_t memory, uint32_t parallel)
36 {
37 #if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
38         return -EINVAL;
39 #else
40         argon2_type atype;
41         argon2_context context = {
42                 .flags = ARGON2_DEFAULT_FLAGS,
43                 .version = ARGON2_VERSION_NUMBER,
44                 .t_cost = (uint32_t)iterations,
45                 .m_cost = (uint32_t)memory,
46                 .lanes = (uint32_t)parallel,
47                 .threads = (uint32_t)parallel,
48                 .out = (uint8_t *)key,
49                 .outlen = (uint32_t)key_length,
50                 .pwd = CONST_CAST(uint8_t *)password,
51                 .pwdlen = (uint32_t)password_length,
52                 .salt = CONST_CAST(uint8_t *)salt,
53                 .saltlen = (uint32_t)salt_length,
54         };
55         int r;
56
57         if (!strcmp(type, "argon2i"))
58                 atype = Argon2_i;
59         else if(!strcmp(type, "argon2id"))
60                 atype = Argon2_id;
61         else
62                 return -EINVAL;
63
64         switch (argon2_ctx(&context, atype)) {
65         case ARGON2_OK:
66                 r = 0;
67                 break;
68         case ARGON2_MEMORY_ALLOCATION_ERROR:
69         case ARGON2_FREE_MEMORY_CBK_NULL:
70         case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
71                 r = -ENOMEM;
72                 break;
73         default:
74                 r = -EINVAL;
75         }
76
77         return r;
78 #endif
79 }