2 * Copyright (C) 2016 Raptor Engineering, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #if defined(HAVE_CONFIG_H)
29 #include <sys/types.h>
32 #include <file/file.h>
33 #include <talloc/talloc.h>
35 #include <util/util.h>
36 #include <i18n/i18n.h>
43 * If --with-signed-boot is enabled lib/security provides the ability to handle
44 * gpg-signed and/or encrypted boot sources (kernel, initrd, etc).
45 * This can be used to enable a form of secure boot, but it is important to
46 * recognise that it depends on the security of the entire system, for example
47 * a full trusted-boot implementation. Petitboot can not and will not be able
48 * to guarantee secure boot by itself.
51 int decrypt_file(const char *filename,
52 FILE *authorized_signatures_handle, const char *keyring_path)
56 size_t bytes_read = 0;
57 unsigned char buffer[8192];
62 gpgme_signature_t verification_signatures;
63 gpgme_verify_result_t verification_result;
64 gpgme_data_t ciphertext_data;
65 gpgme_data_t plaintext_data;
66 gpgme_engine_info_t enginfo;
67 gpgme_ctx_t gpg_context;
70 /* Initialize gpgme */
71 setlocale (LC_ALL, "");
72 gpgme_check_version(NULL);
73 gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
74 err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
75 if (err != GPG_ERR_NO_ERROR) {
76 pb_log_fn("OpenPGP support not available\n");
79 err = gpgme_get_engine_info(&enginfo);
80 if (err != GPG_ERR_NO_ERROR) {
81 pb_log_fn("GPG engine failed to initialize\n");
84 err = gpgme_new(&gpg_context);
85 if (err != GPG_ERR_NO_ERROR) {
86 pb_log_fn("GPG context could not be created\n");
89 err = gpgme_set_protocol(gpg_context, GPGME_PROTOCOL_OpenPGP);
90 if (err != GPG_ERR_NO_ERROR) {
91 pb_log_fn("GPG protocol could not be set\n");
95 err = gpgme_ctx_set_engine_info (gpg_context,
96 GPGME_PROTOCOL_OpenPGP,
97 enginfo->file_name, keyring_path);
99 err = gpgme_ctx_set_engine_info (gpg_context,
100 GPGME_PROTOCOL_OpenPGP,
101 enginfo->file_name, enginfo->home_dir);
102 if (err != GPG_ERR_NO_ERROR) {
103 pb_log_fn("Could not set GPG engine information\n");
106 err = gpgme_data_new(&plaintext_data);
107 if (err != GPG_ERR_NO_ERROR) {
108 pb_log("%s: Could not create GPG plaintext data buffer\n",
112 err = gpgme_data_new_from_file(&ciphertext_data, filename, 1);
113 if (err != GPG_ERR_NO_ERROR) {
114 pb_log("%s: Could not create GPG ciphertext data buffer"
115 " from file '%s'\n", __func__, filename);
119 /* Decrypt and verify file */
120 err = gpgme_op_decrypt_verify(gpg_context, ciphertext_data,
122 if (err != GPG_ERR_NO_ERROR) {
123 pb_log_fn("Could not decrypt file\n");
126 verification_result = gpgme_op_verify_result(gpg_context);
127 verification_signatures = verification_result->signatures;
128 while (verification_signatures) {
129 if (verification_signatures->status == GPG_ERR_NO_ERROR) {
130 pb_log("%s: Good signature for key ID '%s' ('%s')\n",
132 verification_signatures->fpr, filename);
133 /* Verify fingerprint is present in authorized
136 char *auth_sig_line = NULL;
137 size_t auth_sig_len = 0;
138 ssize_t auth_sig_read;
139 rewind(authorized_signatures_handle);
140 while ((auth_sig_read = getline(&auth_sig_line,
142 authorized_signatures_handle)) != -1) {
143 auth_sig_len = strlen(auth_sig_line);
144 while ((auth_sig_line[auth_sig_len-1] == '\n')
145 || (auth_sig_line[auth_sig_len-1] == '\r'))
147 auth_sig_line[auth_sig_len] = 0;
148 if (strcmp(auth_sig_line,
149 verification_signatures->fpr) == 0)
155 pb_log("%s: Signature for key ID '%s' ('%s') invalid."
156 " Status: %08x\n", __func__,
157 verification_signatures->fpr, filename,
158 verification_signatures->status);
160 verification_signatures = verification_signatures->next;
163 gpgme_data_release(ciphertext_data);
166 /* Write decrypted file over ciphertext */
167 FILE *plaintext_file_handle = NULL;
168 plaintext_file_handle = fopen(filename, "wb");
169 if (!plaintext_file_handle) {
170 pb_log("%s: Could not create GPG plaintext file '%s'\n",
172 gpgme_data_release(plaintext_data);
173 gpgme_release(gpg_context);
176 gpgme_data_seek(plaintext_data, 0, SEEK_SET);
177 if (err != GPG_ERR_NO_ERROR) {
178 pb_log("%s: Could not seek in GPG plaintext buffer\n",
180 gpgme_data_release(plaintext_data);
181 gpgme_release(gpg_context);
182 fclose(plaintext_file_handle);
185 while ((bytes_read = gpgme_data_read(plaintext_data, buffer,
187 size_t l2 = fwrite(buffer, 1, bytes_read,
188 plaintext_file_handle);
189 if (l2 < bytes_read) {
190 if (ferror(plaintext_file_handle)) {
193 pb_log("%s: failed: unknown fault\n",
197 /* No space on destination device */
199 pb_log("%s: failed: temporary storage"
200 " full\n", __func__);
205 fclose(plaintext_file_handle);
209 gpgme_data_release(plaintext_data);
210 gpgme_release(gpg_context);
213 pb_log_fn("Incorrect GPG signature\n");
217 pb_log("%s: GPG signature for decrypted file '%s' verified\n",
223 int verify_file_signature(const char *plaintext_filename,
224 const char *signature_filename, FILE *authorized_signatures_handle,
225 const char *keyring_path)
228 gpgme_signature_t verification_signatures;
229 gpgme_verify_result_t verification_result;
230 gpgme_data_t plaintext_data;
231 gpgme_data_t signature_data;
232 gpgme_engine_info_t enginfo;
233 gpgme_ctx_t gpg_context;
236 if (signature_filename == NULL)
239 /* Initialize gpgme */
240 setlocale (LC_ALL, "");
241 gpgme_check_version(NULL);
242 gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
243 err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
244 if (err != GPG_ERR_NO_ERROR) {
245 pb_log_fn("OpenPGP support not available\n");
248 err = gpgme_get_engine_info(&enginfo);
249 if (err != GPG_ERR_NO_ERROR) {
250 pb_log_fn("GPG engine failed to initialize\n");
253 err = gpgme_new(&gpg_context);
254 if (err != GPG_ERR_NO_ERROR) {
255 pb_log_fn("GPG context could not be created\n");
258 err = gpgme_set_protocol(gpg_context, GPGME_PROTOCOL_OpenPGP);
259 if (err != GPG_ERR_NO_ERROR) {
260 pb_log_fn("GPG protocol could not be set\n");
264 err = gpgme_ctx_set_engine_info (gpg_context,
265 GPGME_PROTOCOL_OpenPGP, enginfo->file_name,
268 err = gpgme_ctx_set_engine_info (gpg_context,
269 GPGME_PROTOCOL_OpenPGP, enginfo->file_name,
271 if (err != GPG_ERR_NO_ERROR) {
272 pb_log_fn("Could not set GPG engine information\n");
275 err = gpgme_data_new_from_file(&plaintext_data, plaintext_filename, 1);
276 if (err != GPG_ERR_NO_ERROR) {
277 pb_log("%s: Could not create GPG plaintext data buffer"
278 " from file '%s'\n", __func__, plaintext_filename);
281 err = gpgme_data_new_from_file(&signature_data, signature_filename, 1);
282 if (err != GPG_ERR_NO_ERROR) {
283 pb_log("%s: Could not create GPG signature data buffer"
284 " from file '%s'\n", __func__, signature_filename);
288 /* Check signature */
289 err = gpgme_op_verify(gpg_context, signature_data, plaintext_data,
291 if (err != GPG_ERR_NO_ERROR) {
292 pb_log("%s: Could not verify file using GPG signature '%s'\n",
293 __func__, signature_filename);
296 verification_result = gpgme_op_verify_result(gpg_context);
297 verification_signatures = verification_result->signatures;
298 while (verification_signatures) {
299 if (verification_signatures->status != GPG_ERR_NO_ERROR) {
300 /* Signature verification failure */
301 pb_log("%s: Signature for key ID '%s' ('%s') invalid."
302 " Status: %08x\n", __func__,
303 verification_signatures->fpr,
305 verification_signatures->status);
306 verification_signatures = verification_signatures->next;
310 /* Signature check passed with no error */
311 pb_log("%s: Good signature for key ID '%s' ('%s')\n",
312 __func__, verification_signatures->fpr,
314 /* Verify fingerprint is present in
315 * authorized signatures file
317 char *auth_sig_line = NULL;
318 size_t auth_sig_len = 0;
319 ssize_t auth_sig_read;
320 rewind(authorized_signatures_handle);
321 while ((auth_sig_read = getline(&auth_sig_line,
323 authorized_signatures_handle)) != -1) {
324 auth_sig_len = strlen(auth_sig_line);
325 while ((auth_sig_line[auth_sig_len-1] == '\n')
326 || (auth_sig_line[auth_sig_len-1] == '\r'))
328 auth_sig_line[auth_sig_len] = '\0';
329 if (strcmp(auth_sig_line,
330 verification_signatures->fpr) == 0)
334 verification_signatures = verification_signatures->next;
338 gpgme_data_release(plaintext_data);
339 gpgme_data_release(signature_data);
340 gpgme_release(gpg_context);
343 pb_log_fn("Incorrect GPG signature\n");
347 pb_log("%s: GPG signature '%s' for file '%s' verified\n",
348 __func__, signature_filename, plaintext_filename);
353 int lockdown_status() {
354 /* assume most restrictive lockdown type */
355 int ret = PB_LOCKDOWN_SIGN;
357 #if !defined(HARD_LOCKDOWN)
358 if (access(LOCKDOWN_FILE, F_OK) == -1)
359 return PB_LOCKDOWN_NONE;
362 /* determine lockdown type */
363 FILE *authorized_signatures_handle = NULL;
364 authorized_signatures_handle = fopen(LOCKDOWN_FILE, "r");
365 if (!authorized_signatures_handle)
368 char *auth_sig_line = NULL;
369 size_t auth_sig_len = 0;
370 ssize_t auth_sig_read;
371 rewind(authorized_signatures_handle);
372 if ((auth_sig_read = getline(&auth_sig_line,
374 authorized_signatures_handle)) != -1) {
375 auth_sig_len = strlen(auth_sig_line);
376 while ((auth_sig_line[auth_sig_len-1] == '\n')
377 || (auth_sig_line[auth_sig_len-1] == '\r'))
379 auth_sig_line[auth_sig_len] = 0;
380 if (strcmp(auth_sig_line, "ENCRYPTED") == 0) {
381 /* first line indicates encrypted files
382 * expected. enable decryption.
384 ret = PB_LOCKDOWN_DECRYPT;