]>
Commit | Line | Data |
---|---|---|
aecbc87d LP |
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 | } |