]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/home/modhex.c
core: reduce scope of variants
[thirdparty/systemd.git] / src / home / modhex.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4
5 #include "modhex.h"
6 #include "macro.h"
7 #include "memory-util.h"
8
9 const char modhex_alphabet[16] = {
10 'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v'
11 };
12
13 int decode_modhex_char(char x) {
14
15 for (size_t i = 0; i < ELEMENTSOF(modhex_alphabet); i++)
16 /* Check both upper and lowercase */
17 if (modhex_alphabet[i] == x || (modhex_alphabet[i] - 32) == x)
18 return i;
19
20 return -EINVAL;
21 }
22
23 int normalize_recovery_key(const char *password, char **ret) {
24 _cleanup_(erase_and_freep) char *mangled = NULL;
25 size_t l;
26
27 assert(password);
28 assert(ret);
29
30 l = strlen(password);
31 if (!IN_SET(l,
32 MODHEX_RAW_LENGTH*2, /* syntax without dashes */
33 MODHEX_FORMATTED_LENGTH-1)) /* syntax with dashes */
34 return -EINVAL;
35
36 mangled = new(char, MODHEX_FORMATTED_LENGTH);
37 if (!mangled)
38 return -ENOMEM;
39
40 for (size_t i = 0, j = 0; i < MODHEX_RAW_LENGTH; i++) {
41 size_t k;
42 int a, b;
43
44 if (l == MODHEX_RAW_LENGTH*2)
45 /* Syntax without dashes */
46 k = i * 2;
47 else {
48 /* Syntax with dashes */
49 assert(l == MODHEX_FORMATTED_LENGTH-1);
50 k = i * 2 + i / 4;
51
52 if (i > 0 && i % 4 == 0 && password[k-1] != '-')
53 return -EINVAL;
54 }
55
56 a = decode_modhex_char(password[k]);
57 if (a < 0)
58 return -EINVAL;
59 b = decode_modhex_char(password[k+1]);
60 if (b < 0)
61 return -EINVAL;
62
63 mangled[j++] = modhex_alphabet[a];
64 mangled[j++] = modhex_alphabet[b];
65
66 if (i % 4 == 3)
67 mangled[j++] = '-';
68 }
69
70 mangled[MODHEX_FORMATTED_LENGTH-1] = 0;
71
72 *ret = TAKE_PTR(mangled);
73 return 0;
74 }