Merge branch 'upstream' into tizen
[platform/upstream/cryptsetup.git] / src / utils_luks2.c
1 /*
2  * Helper utilities for LUKS2 features
3  *
4  * Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2018-2021 Milan Broz
6  * Copyright (C) 2018-2021 Ondrej Kozina
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "cryptsetup.h"
24
25 /*
26  * FIXME: 4MiBs is max LUKS2 mda length (including binary header).
27  * In future, read max allowed JSON size from config section.
28  */
29 #define LUKS2_MAX_MDA_SIZE 0x400000
30 int tools_read_json_file(struct crypt_device *cd, const char *file, char **json, size_t *json_size)
31 {
32         ssize_t ret;
33         int fd, block, r;
34         void *buf = NULL;
35
36         block = tools_signals_blocked();
37         if (block)
38                 set_int_block(0);
39
40         if (tools_is_stdin(file)) {
41                 fd = STDIN_FILENO;
42                 log_dbg("STDIN descriptor JSON read requested.");
43         } else {
44                 log_dbg("File descriptor JSON read requested.");
45                 fd = open(file, O_RDONLY);
46                 if (fd < 0) {
47                         log_err(_("Failed to open file %s in read-only mode."), file);
48                         r = -EINVAL;
49                         goto out;
50                 }
51         }
52
53         buf = malloc(LUKS2_MAX_MDA_SIZE);
54         if (!buf) {
55                 r = -ENOMEM;
56                 goto out;
57         }
58
59         if (isatty(fd) && !opt_batch_mode)
60                 log_std(_("Provide valid LUKS2 token JSON:\n"));
61
62         /* we expect JSON (string) */
63         r = 0;
64         ret = read_buffer_intr(fd, buf, LUKS2_MAX_MDA_SIZE - 1, &quit);
65         if (ret < 0) {
66                 r = -EIO;
67                 log_err(_("Failed to read JSON file."));
68                 goto out;
69         }
70         check_signal(&r);
71         if (r) {
72                 log_err(_("\nRead interrupted."));
73                 goto out;
74         }
75
76         *json_size = (size_t)ret;
77         *json = buf;
78         *(*json + ret) = '\0';
79 out:
80         if (block && !quit)
81                 set_int_block(1);
82         if (fd >= 0 && fd != STDIN_FILENO)
83                 close(fd);
84         if (r && buf) {
85                 memset(buf, 0, LUKS2_MAX_MDA_SIZE);
86                 free(buf);
87         }
88         return r;
89 }
90
91 int tools_write_json_file(struct crypt_device *cd, const char *file, const char *json)
92 {
93         int block, fd, r;
94         size_t json_len;
95         ssize_t ret;
96
97         if (!json || !(json_len = strlen(json)) || json_len >= LUKS2_MAX_MDA_SIZE)
98                 return -EINVAL;
99
100         block = tools_signals_blocked();
101         if (block)
102                 set_int_block(0);
103
104         if (tools_is_stdin(file)) {
105                 fd = STDOUT_FILENO;
106                 log_dbg("STDOUT descriptor JSON write requested.");
107         } else {
108                 log_dbg("File descriptor JSON write requested.");
109                 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
110         }
111
112         if (fd < 0) {
113                 log_err(_("Failed to open file %s in write mode."), file ?: "");
114                 r = -EINVAL;
115                 goto out;
116         }
117
118         r = 0;
119         ret = write_buffer_intr(fd, json, json_len, &quit);
120         check_signal(&r);
121         if (r) {
122                 log_err(_("\nWrite interrupted."));
123                 goto out;
124         }
125         if (ret < 0 || (size_t)ret != json_len) {
126                 log_err(_("Failed to write JSON file."));
127                 r = -EIO;
128                 goto out;
129         }
130
131         if (isatty(fd))
132                 (void) write_buffer_intr(fd, "\n", 1, &quit);
133 out:
134         if (block && !quit)
135                 set_int_block(1);
136         if (fd >=0 && fd != STDOUT_FILENO)
137                 close(fd);
138         return r;
139 }