1480f31c2SKonrad Witaszczyk /*- 2480f31c2SKonrad Witaszczyk * Copyright (c) 2016 Konrad Witaszczyk <def@FreeBSD.org> 3480f31c2SKonrad Witaszczyk * All rights reserved. 4480f31c2SKonrad Witaszczyk * 5480f31c2SKonrad Witaszczyk * Redistribution and use in source and binary forms, with or without 6480f31c2SKonrad Witaszczyk * modification, are permitted provided that the following conditions 7480f31c2SKonrad Witaszczyk * are met: 8480f31c2SKonrad Witaszczyk * 1. Redistributions of source code must retain the above copyright 9480f31c2SKonrad Witaszczyk * notice, this list of conditions and the following disclaimer. 10480f31c2SKonrad Witaszczyk * 2. Redistributions in binary form must reproduce the above copyright 11480f31c2SKonrad Witaszczyk * notice, this list of conditions and the following disclaimer in the 12480f31c2SKonrad Witaszczyk * documentation and/or other materials provided with the distribution. 13480f31c2SKonrad Witaszczyk * 14480f31c2SKonrad Witaszczyk * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15480f31c2SKonrad Witaszczyk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16480f31c2SKonrad Witaszczyk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17480f31c2SKonrad Witaszczyk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18480f31c2SKonrad Witaszczyk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19480f31c2SKonrad Witaszczyk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20480f31c2SKonrad Witaszczyk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21480f31c2SKonrad Witaszczyk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22480f31c2SKonrad Witaszczyk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23480f31c2SKonrad Witaszczyk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24480f31c2SKonrad Witaszczyk * SUCH DAMAGE. 25480f31c2SKonrad Witaszczyk */ 26480f31c2SKonrad Witaszczyk 27480f31c2SKonrad Witaszczyk #include <sys/cdefs.h> 28480f31c2SKonrad Witaszczyk __FBSDID("$FreeBSD$"); 29480f31c2SKonrad Witaszczyk 30480f31c2SKonrad Witaszczyk #include <sys/types.h> 31480f31c2SKonrad Witaszczyk #include <sys/capsicum.h> 32480f31c2SKonrad Witaszczyk #include <sys/endian.h> 33480f31c2SKonrad Witaszczyk #include <sys/kerneldump.h> 34480f31c2SKonrad Witaszczyk #include <sys/sysctl.h> 35480f31c2SKonrad Witaszczyk #include <sys/wait.h> 36480f31c2SKonrad Witaszczyk 37480f31c2SKonrad Witaszczyk #include <ctype.h> 387672a014SMariusz Zaborski #include <capsicum_helpers.h> 39480f31c2SKonrad Witaszczyk #include <fcntl.h> 40480f31c2SKonrad Witaszczyk #include <stdbool.h> 41480f31c2SKonrad Witaszczyk #include <stdlib.h> 42480f31c2SKonrad Witaszczyk #include <string.h> 43480f31c2SKonrad Witaszczyk #include <unistd.h> 44480f31c2SKonrad Witaszczyk 45480f31c2SKonrad Witaszczyk #include <openssl/evp.h> 46480f31c2SKonrad Witaszczyk #include <openssl/pem.h> 47480f31c2SKonrad Witaszczyk #include <openssl/rsa.h> 48480f31c2SKonrad Witaszczyk #include <openssl/engine.h> 49480f31c2SKonrad Witaszczyk 50480f31c2SKonrad Witaszczyk #include "pjdlog.h" 51480f31c2SKonrad Witaszczyk 52480f31c2SKonrad Witaszczyk #define DECRYPTCORE_CRASHDIR "/var/crash" 53480f31c2SKonrad Witaszczyk 54480f31c2SKonrad Witaszczyk static void 55480f31c2SKonrad Witaszczyk usage(void) 56480f31c2SKonrad Witaszczyk { 57480f31c2SKonrad Witaszczyk 58480f31c2SKonrad Witaszczyk pjdlog_exitx(1, 594b30cd46SKonrad Witaszczyk "usage: decryptcore [-fLv] -p privatekeyfile -k keyfile -e encryptedcore -c core\n" 604b30cd46SKonrad Witaszczyk " decryptcore [-fLv] [-d crashdir] -p privatekeyfile -n dumpnr"); 61480f31c2SKonrad Witaszczyk } 62480f31c2SKonrad Witaszczyk 63480f31c2SKonrad Witaszczyk static int 64480f31c2SKonrad Witaszczyk wait_for_process(pid_t pid) 65480f31c2SKonrad Witaszczyk { 66480f31c2SKonrad Witaszczyk int status; 67480f31c2SKonrad Witaszczyk 68480f31c2SKonrad Witaszczyk if (waitpid(pid, &status, WUNTRACED | WEXITED) == -1) { 69480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to wait for a child process"); 70480f31c2SKonrad Witaszczyk return (1); 71480f31c2SKonrad Witaszczyk } 72480f31c2SKonrad Witaszczyk 73480f31c2SKonrad Witaszczyk if (WIFEXITED(status)) 74480f31c2SKonrad Witaszczyk return (WEXITSTATUS(status)); 75480f31c2SKonrad Witaszczyk 76480f31c2SKonrad Witaszczyk return (1); 77480f31c2SKonrad Witaszczyk } 78480f31c2SKonrad Witaszczyk 79480f31c2SKonrad Witaszczyk static struct kerneldumpkey * 80480f31c2SKonrad Witaszczyk read_key(int kfd) 81480f31c2SKonrad Witaszczyk { 82480f31c2SKonrad Witaszczyk struct kerneldumpkey *kdk; 83480f31c2SKonrad Witaszczyk ssize_t size; 84480f31c2SKonrad Witaszczyk size_t kdksize; 85480f31c2SKonrad Witaszczyk 86480f31c2SKonrad Witaszczyk PJDLOG_ASSERT(kfd >= 0); 87480f31c2SKonrad Witaszczyk 88480f31c2SKonrad Witaszczyk kdksize = sizeof(*kdk); 89480f31c2SKonrad Witaszczyk kdk = calloc(1, kdksize); 90480f31c2SKonrad Witaszczyk if (kdk == NULL) { 91480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to allocate kernel dump key"); 92480f31c2SKonrad Witaszczyk goto failed; 93480f31c2SKonrad Witaszczyk } 94480f31c2SKonrad Witaszczyk 95480f31c2SKonrad Witaszczyk size = read(kfd, kdk, kdksize); 96480f31c2SKonrad Witaszczyk if (size == (ssize_t)kdksize) { 97480f31c2SKonrad Witaszczyk kdk->kdk_encryptedkeysize = dtoh32(kdk->kdk_encryptedkeysize); 98480f31c2SKonrad Witaszczyk kdksize += (size_t)kdk->kdk_encryptedkeysize; 99480f31c2SKonrad Witaszczyk kdk = realloc(kdk, kdksize); 100480f31c2SKonrad Witaszczyk if (kdk == NULL) { 101480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to reallocate kernel dump key"); 102480f31c2SKonrad Witaszczyk goto failed; 103480f31c2SKonrad Witaszczyk } 104480f31c2SKonrad Witaszczyk size += read(kfd, &kdk->kdk_encryptedkey, 105480f31c2SKonrad Witaszczyk kdk->kdk_encryptedkeysize); 106480f31c2SKonrad Witaszczyk } 107480f31c2SKonrad Witaszczyk if (size != (ssize_t)kdksize) { 108480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to read key"); 109480f31c2SKonrad Witaszczyk goto failed; 110480f31c2SKonrad Witaszczyk } 111480f31c2SKonrad Witaszczyk 112480f31c2SKonrad Witaszczyk return (kdk); 113480f31c2SKonrad Witaszczyk failed: 114480f31c2SKonrad Witaszczyk free(kdk); 115480f31c2SKonrad Witaszczyk return (NULL); 116480f31c2SKonrad Witaszczyk } 117480f31c2SKonrad Witaszczyk 118480f31c2SKonrad Witaszczyk static bool 1194b30cd46SKonrad Witaszczyk decrypt(int ofd, const char *privkeyfile, const char *keyfile, 1204b30cd46SKonrad Witaszczyk const char *input) 121480f31c2SKonrad Witaszczyk { 12282985292SConrad Meyer uint8_t buf[KERNELDUMP_BUFFER_SIZE], key[KERNELDUMP_KEY_MAX_SIZE], 12382985292SConrad Meyer chachaiv[4 * 4]; 1243548eb3aSJung-uk Kim EVP_CIPHER_CTX *ctx; 125480f31c2SKonrad Witaszczyk const EVP_CIPHER *cipher; 126480f31c2SKonrad Witaszczyk FILE *fp; 127480f31c2SKonrad Witaszczyk struct kerneldumpkey *kdk; 128480f31c2SKonrad Witaszczyk RSA *privkey; 1294b30cd46SKonrad Witaszczyk int ifd, kfd, olen, privkeysize; 130480f31c2SKonrad Witaszczyk ssize_t bytes; 131480f31c2SKonrad Witaszczyk pid_t pid; 132480f31c2SKonrad Witaszczyk 1334b30cd46SKonrad Witaszczyk PJDLOG_ASSERT(ofd >= 0); 134480f31c2SKonrad Witaszczyk PJDLOG_ASSERT(privkeyfile != NULL); 135480f31c2SKonrad Witaszczyk PJDLOG_ASSERT(keyfile != NULL); 136480f31c2SKonrad Witaszczyk PJDLOG_ASSERT(input != NULL); 137480f31c2SKonrad Witaszczyk 1383548eb3aSJung-uk Kim ctx = NULL; 139480f31c2SKonrad Witaszczyk privkey = NULL; 140480f31c2SKonrad Witaszczyk 141480f31c2SKonrad Witaszczyk /* 142480f31c2SKonrad Witaszczyk * Decrypt a core dump in a child process so we can unlink a partially 143480f31c2SKonrad Witaszczyk * decrypted core if the child process fails. 144480f31c2SKonrad Witaszczyk */ 145480f31c2SKonrad Witaszczyk pid = fork(); 146480f31c2SKonrad Witaszczyk if (pid == -1) { 147480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to create child process"); 1484b30cd46SKonrad Witaszczyk close(ofd); 149480f31c2SKonrad Witaszczyk return (false); 150480f31c2SKonrad Witaszczyk } 151480f31c2SKonrad Witaszczyk 1524b30cd46SKonrad Witaszczyk if (pid > 0) { 1534b30cd46SKonrad Witaszczyk close(ofd); 154480f31c2SKonrad Witaszczyk return (wait_for_process(pid) == 0); 1554b30cd46SKonrad Witaszczyk } 156480f31c2SKonrad Witaszczyk 157480f31c2SKonrad Witaszczyk kfd = open(keyfile, O_RDONLY); 158480f31c2SKonrad Witaszczyk if (kfd == -1) { 159480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile); 160480f31c2SKonrad Witaszczyk goto failed; 161480f31c2SKonrad Witaszczyk } 162480f31c2SKonrad Witaszczyk ifd = open(input, O_RDONLY); 163480f31c2SKonrad Witaszczyk if (ifd == -1) { 164480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to open %s", input); 165480f31c2SKonrad Witaszczyk goto failed; 166480f31c2SKonrad Witaszczyk } 167480f31c2SKonrad Witaszczyk fp = fopen(privkeyfile, "r"); 168480f31c2SKonrad Witaszczyk if (fp == NULL) { 169480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile); 170480f31c2SKonrad Witaszczyk goto failed; 171480f31c2SKonrad Witaszczyk } 172480f31c2SKonrad Witaszczyk 1737672a014SMariusz Zaborski if (caph_enter() < 0) { 174480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to enter capability mode"); 175480f31c2SKonrad Witaszczyk goto failed; 176480f31c2SKonrad Witaszczyk } 177480f31c2SKonrad Witaszczyk 178480f31c2SKonrad Witaszczyk privkey = RSA_new(); 179480f31c2SKonrad Witaszczyk if (privkey == NULL) { 180480f31c2SKonrad Witaszczyk pjdlog_error("Unable to allocate an RSA structure: %s", 181480f31c2SKonrad Witaszczyk ERR_error_string(ERR_get_error(), NULL)); 182480f31c2SKonrad Witaszczyk goto failed; 183480f31c2SKonrad Witaszczyk } 1843548eb3aSJung-uk Kim ctx = EVP_CIPHER_CTX_new(); 1853548eb3aSJung-uk Kim if (ctx == NULL) 1863548eb3aSJung-uk Kim goto failed; 187480f31c2SKonrad Witaszczyk 188480f31c2SKonrad Witaszczyk kdk = read_key(kfd); 189480f31c2SKonrad Witaszczyk close(kfd); 190480f31c2SKonrad Witaszczyk if (kdk == NULL) 191480f31c2SKonrad Witaszczyk goto failed; 192480f31c2SKonrad Witaszczyk 193480f31c2SKonrad Witaszczyk privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL); 194480f31c2SKonrad Witaszczyk fclose(fp); 195480f31c2SKonrad Witaszczyk if (privkey == NULL) { 196480f31c2SKonrad Witaszczyk pjdlog_error("Unable to read data from %s.", privkeyfile); 197480f31c2SKonrad Witaszczyk goto failed; 198480f31c2SKonrad Witaszczyk } 199480f31c2SKonrad Witaszczyk 200480f31c2SKonrad Witaszczyk privkeysize = RSA_size(privkey); 201480f31c2SKonrad Witaszczyk if (privkeysize != (int)kdk->kdk_encryptedkeysize) { 202480f31c2SKonrad Witaszczyk pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.", 203480f31c2SKonrad Witaszczyk 8 * privkeysize, 8 * kdk->kdk_encryptedkeysize); 204480f31c2SKonrad Witaszczyk goto failed; 205480f31c2SKonrad Witaszczyk } 206480f31c2SKonrad Witaszczyk 207480f31c2SKonrad Witaszczyk switch (kdk->kdk_encryption) { 208480f31c2SKonrad Witaszczyk case KERNELDUMP_ENC_AES_256_CBC: 209480f31c2SKonrad Witaszczyk cipher = EVP_aes_256_cbc(); 210480f31c2SKonrad Witaszczyk break; 21182985292SConrad Meyer case KERNELDUMP_ENC_CHACHA20: 21282985292SConrad Meyer cipher = EVP_chacha20(); 21382985292SConrad Meyer break; 214480f31c2SKonrad Witaszczyk default: 215480f31c2SKonrad Witaszczyk pjdlog_error("Invalid encryption algorithm."); 216480f31c2SKonrad Witaszczyk goto failed; 217480f31c2SKonrad Witaszczyk } 218480f31c2SKonrad Witaszczyk 219480f31c2SKonrad Witaszczyk if (RSA_private_decrypt(kdk->kdk_encryptedkeysize, 220480f31c2SKonrad Witaszczyk kdk->kdk_encryptedkey, key, privkey, 221480f31c2SKonrad Witaszczyk RSA_PKCS1_PADDING) != sizeof(key)) { 222480f31c2SKonrad Witaszczyk pjdlog_error("Unable to decrypt key: %s", 223480f31c2SKonrad Witaszczyk ERR_error_string(ERR_get_error(), NULL)); 224480f31c2SKonrad Witaszczyk goto failed; 225480f31c2SKonrad Witaszczyk } 226480f31c2SKonrad Witaszczyk RSA_free(privkey); 227480f31c2SKonrad Witaszczyk privkey = NULL; 228480f31c2SKonrad Witaszczyk 22982985292SConrad Meyer if (kdk->kdk_encryption == KERNELDUMP_ENC_CHACHA20) { 23082985292SConrad Meyer /* 23182985292SConrad Meyer * OpenSSL treats the IV as 4 little-endian 32 bit integers. 23282985292SConrad Meyer * 23382985292SConrad Meyer * The first two represent a 64-bit counter, where the low half 23482985292SConrad Meyer * is the first 32-bit word. 23582985292SConrad Meyer * 23682985292SConrad Meyer * Start at counter block zero... 23782985292SConrad Meyer */ 23882985292SConrad Meyer memset(chachaiv, 0, 4 * 2); 23982985292SConrad Meyer /* 24082985292SConrad Meyer * And use the IV specified by the dump. 24182985292SConrad Meyer */ 24282985292SConrad Meyer memcpy(&chachaiv[4 * 2], kdk->kdk_iv, 4 * 2); 24382985292SConrad Meyer EVP_DecryptInit_ex(ctx, cipher, NULL, key, chachaiv); 24482985292SConrad Meyer } else 2453548eb3aSJung-uk Kim EVP_DecryptInit_ex(ctx, cipher, NULL, key, kdk->kdk_iv); 2463548eb3aSJung-uk Kim EVP_CIPHER_CTX_set_padding(ctx, 0); 247480f31c2SKonrad Witaszczyk 248480f31c2SKonrad Witaszczyk explicit_bzero(key, sizeof(key)); 249480f31c2SKonrad Witaszczyk 250480f31c2SKonrad Witaszczyk do { 251480f31c2SKonrad Witaszczyk bytes = read(ifd, buf, sizeof(buf)); 252480f31c2SKonrad Witaszczyk if (bytes < 0) { 253480f31c2SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to read data from %s", 254480f31c2SKonrad Witaszczyk input); 255480f31c2SKonrad Witaszczyk goto failed; 256480f31c2SKonrad Witaszczyk } 257480f31c2SKonrad Witaszczyk 258480f31c2SKonrad Witaszczyk if (bytes > 0) { 2593548eb3aSJung-uk Kim if (EVP_DecryptUpdate(ctx, buf, &olen, buf, 260480f31c2SKonrad Witaszczyk bytes) == 0) { 261480f31c2SKonrad Witaszczyk pjdlog_error("Unable to decrypt core."); 262480f31c2SKonrad Witaszczyk goto failed; 263480f31c2SKonrad Witaszczyk } 264480f31c2SKonrad Witaszczyk } else { 2653548eb3aSJung-uk Kim if (EVP_DecryptFinal_ex(ctx, buf, &olen) == 0) { 266480f31c2SKonrad Witaszczyk pjdlog_error("Unable to decrypt core."); 267480f31c2SKonrad Witaszczyk goto failed; 268480f31c2SKonrad Witaszczyk } 269480f31c2SKonrad Witaszczyk } 270480f31c2SKonrad Witaszczyk 2713c7ccf15SKonrad Witaszczyk if (olen > 0 && write(ofd, buf, olen) != olen) { 2724b30cd46SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to write core"); 273480f31c2SKonrad Witaszczyk goto failed; 274480f31c2SKonrad Witaszczyk } 275480f31c2SKonrad Witaszczyk } while (bytes > 0); 276480f31c2SKonrad Witaszczyk 277480f31c2SKonrad Witaszczyk explicit_bzero(buf, sizeof(buf)); 2783548eb3aSJung-uk Kim EVP_CIPHER_CTX_free(ctx); 279480f31c2SKonrad Witaszczyk exit(0); 280480f31c2SKonrad Witaszczyk failed: 281480f31c2SKonrad Witaszczyk explicit_bzero(key, sizeof(key)); 282480f31c2SKonrad Witaszczyk explicit_bzero(buf, sizeof(buf)); 283480f31c2SKonrad Witaszczyk RSA_free(privkey); 2843548eb3aSJung-uk Kim if (ctx != NULL) 2853548eb3aSJung-uk Kim EVP_CIPHER_CTX_free(ctx); 286480f31c2SKonrad Witaszczyk exit(1); 287480f31c2SKonrad Witaszczyk } 288480f31c2SKonrad Witaszczyk 289480f31c2SKonrad Witaszczyk int 290480f31c2SKonrad Witaszczyk main(int argc, char **argv) 291480f31c2SKonrad Witaszczyk { 292480f31c2SKonrad Witaszczyk char core[PATH_MAX], encryptedcore[PATH_MAX], keyfile[PATH_MAX]; 293480f31c2SKonrad Witaszczyk const char *crashdir, *dumpnr, *privatekey; 2944b30cd46SKonrad Witaszczyk int ch, debug, error, ofd; 295480f31c2SKonrad Witaszczyk size_t ii; 2964b30cd46SKonrad Witaszczyk bool force, usesyslog; 2974b30cd46SKonrad Witaszczyk 2984b30cd46SKonrad Witaszczyk error = 1; 299480f31c2SKonrad Witaszczyk 300480f31c2SKonrad Witaszczyk pjdlog_init(PJDLOG_MODE_STD); 301480f31c2SKonrad Witaszczyk pjdlog_prefix_set("(decryptcore) "); 302480f31c2SKonrad Witaszczyk 303480f31c2SKonrad Witaszczyk debug = 0; 304480f31c2SKonrad Witaszczyk *core = '\0'; 305480f31c2SKonrad Witaszczyk crashdir = NULL; 306480f31c2SKonrad Witaszczyk dumpnr = NULL; 307480f31c2SKonrad Witaszczyk *encryptedcore = '\0'; 3084b30cd46SKonrad Witaszczyk force = false; 309480f31c2SKonrad Witaszczyk *keyfile = '\0'; 310480f31c2SKonrad Witaszczyk privatekey = NULL; 311480f31c2SKonrad Witaszczyk usesyslog = false; 3124b30cd46SKonrad Witaszczyk while ((ch = getopt(argc, argv, "Lc:d:e:fk:n:p:v")) != -1) { 313480f31c2SKonrad Witaszczyk switch (ch) { 314480f31c2SKonrad Witaszczyk case 'L': 315480f31c2SKonrad Witaszczyk usesyslog = true; 316480f31c2SKonrad Witaszczyk break; 317480f31c2SKonrad Witaszczyk case 'c': 3183c7ccf15SKonrad Witaszczyk if (strlcpy(core, optarg, sizeof(core)) >= sizeof(core)) 3193c7ccf15SKonrad Witaszczyk pjdlog_exitx(1, "Core file path is too long."); 320480f31c2SKonrad Witaszczyk break; 321480f31c2SKonrad Witaszczyk case 'd': 322480f31c2SKonrad Witaszczyk crashdir = optarg; 323480f31c2SKonrad Witaszczyk break; 324480f31c2SKonrad Witaszczyk case 'e': 3253c7ccf15SKonrad Witaszczyk if (strlcpy(encryptedcore, optarg, 3263c7ccf15SKonrad Witaszczyk sizeof(encryptedcore)) >= sizeof(encryptedcore)) { 3273c7ccf15SKonrad Witaszczyk pjdlog_exitx(1, "Encrypted core file path is too long."); 3283c7ccf15SKonrad Witaszczyk } 329480f31c2SKonrad Witaszczyk break; 3304b30cd46SKonrad Witaszczyk case 'f': 3314b30cd46SKonrad Witaszczyk force = true; 3324b30cd46SKonrad Witaszczyk break; 333480f31c2SKonrad Witaszczyk case 'k': 3343c7ccf15SKonrad Witaszczyk if (strlcpy(keyfile, optarg, sizeof(keyfile)) >= 3353c7ccf15SKonrad Witaszczyk sizeof(keyfile)) { 3363c7ccf15SKonrad Witaszczyk pjdlog_exitx(1, "Key file path is too long."); 3373c7ccf15SKonrad Witaszczyk } 338480f31c2SKonrad Witaszczyk break; 339480f31c2SKonrad Witaszczyk case 'n': 340480f31c2SKonrad Witaszczyk dumpnr = optarg; 341480f31c2SKonrad Witaszczyk break; 342480f31c2SKonrad Witaszczyk case 'p': 343480f31c2SKonrad Witaszczyk privatekey = optarg; 344480f31c2SKonrad Witaszczyk break; 345480f31c2SKonrad Witaszczyk case 'v': 346480f31c2SKonrad Witaszczyk debug++; 347480f31c2SKonrad Witaszczyk break; 348480f31c2SKonrad Witaszczyk default: 349480f31c2SKonrad Witaszczyk usage(); 350480f31c2SKonrad Witaszczyk } 351480f31c2SKonrad Witaszczyk } 352480f31c2SKonrad Witaszczyk argc -= optind; 353480f31c2SKonrad Witaszczyk argv += optind; 354480f31c2SKonrad Witaszczyk 355480f31c2SKonrad Witaszczyk if (argc != 0) 356480f31c2SKonrad Witaszczyk usage(); 357480f31c2SKonrad Witaszczyk 358480f31c2SKonrad Witaszczyk /* Verify mutually exclusive options. */ 359480f31c2SKonrad Witaszczyk if ((crashdir != NULL || dumpnr != NULL) && 360480f31c2SKonrad Witaszczyk (*keyfile != '\0' || *encryptedcore != '\0' || *core != '\0')) { 361480f31c2SKonrad Witaszczyk usage(); 362480f31c2SKonrad Witaszczyk } 363480f31c2SKonrad Witaszczyk 364480f31c2SKonrad Witaszczyk /* 365480f31c2SKonrad Witaszczyk * Set key, encryptedcore and core file names using crashdir and dumpnr. 366480f31c2SKonrad Witaszczyk */ 367480f31c2SKonrad Witaszczyk if (dumpnr != NULL) { 368480f31c2SKonrad Witaszczyk for (ii = 0; ii < strnlen(dumpnr, PATH_MAX); ii++) { 369480f31c2SKonrad Witaszczyk if (isdigit((int)dumpnr[ii]) == 0) 370480f31c2SKonrad Witaszczyk usage(); 371480f31c2SKonrad Witaszczyk } 372480f31c2SKonrad Witaszczyk 373480f31c2SKonrad Witaszczyk if (crashdir == NULL) 374480f31c2SKonrad Witaszczyk crashdir = DECRYPTCORE_CRASHDIR; 375480f31c2SKonrad Witaszczyk PJDLOG_VERIFY(snprintf(keyfile, sizeof(keyfile), 376480f31c2SKonrad Witaszczyk "%s/key.%s", crashdir, dumpnr) > 0); 377480f31c2SKonrad Witaszczyk PJDLOG_VERIFY(snprintf(core, sizeof(core), 378480f31c2SKonrad Witaszczyk "%s/vmcore.%s", crashdir, dumpnr) > 0); 379480f31c2SKonrad Witaszczyk PJDLOG_VERIFY(snprintf(encryptedcore, sizeof(encryptedcore), 380480f31c2SKonrad Witaszczyk "%s/vmcore_encrypted.%s", crashdir, dumpnr) > 0); 381480f31c2SKonrad Witaszczyk } 382480f31c2SKonrad Witaszczyk 383480f31c2SKonrad Witaszczyk if (privatekey == NULL || *keyfile == '\0' || *encryptedcore == '\0' || 384480f31c2SKonrad Witaszczyk *core == '\0') { 385480f31c2SKonrad Witaszczyk usage(); 386480f31c2SKonrad Witaszczyk } 387480f31c2SKonrad Witaszczyk 388480f31c2SKonrad Witaszczyk if (usesyslog) 389480f31c2SKonrad Witaszczyk pjdlog_mode_set(PJDLOG_MODE_SYSLOG); 390480f31c2SKonrad Witaszczyk pjdlog_debug_set(debug); 391480f31c2SKonrad Witaszczyk 3924b30cd46SKonrad Witaszczyk if (force && unlink(core) == -1 && errno != ENOENT) { 3934b30cd46SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to remove old core"); 3944b30cd46SKonrad Witaszczyk goto out; 3954b30cd46SKonrad Witaszczyk } 3964b30cd46SKonrad Witaszczyk ofd = open(core, O_WRONLY | O_CREAT | O_EXCL, 0600); 3974b30cd46SKonrad Witaszczyk if (ofd == -1) { 3984b30cd46SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to open %s", core); 3994b30cd46SKonrad Witaszczyk goto out; 400480f31c2SKonrad Witaszczyk } 401480f31c2SKonrad Witaszczyk 4024b30cd46SKonrad Witaszczyk if (!decrypt(ofd, privatekey, keyfile, encryptedcore)) { 4034b30cd46SKonrad Witaszczyk if (unlink(core) == -1 && errno != ENOENT) 4044b30cd46SKonrad Witaszczyk pjdlog_errno(LOG_ERR, "Unable to remove core"); 4054b30cd46SKonrad Witaszczyk goto out; 4064b30cd46SKonrad Witaszczyk } 407480f31c2SKonrad Witaszczyk 4084b30cd46SKonrad Witaszczyk error = 0; 4094b30cd46SKonrad Witaszczyk out: 4104b30cd46SKonrad Witaszczyk pjdlog_fini(); 4114b30cd46SKonrad Witaszczyk exit(error); 412480f31c2SKonrad Witaszczyk } 413