1 /*- 2 * Copyright (c) 2018, Juniper Networks, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #define NEED_BRSSL_H 30 #include <libsecureboot.h> 31 #include <brssl.h> 32 33 #include "decode.h" 34 35 /** 36 * @brief decode ascii armor 37 * 38 * once we get rid of the trailing checksum 39 * we can treat as PEM. 40 * 41 * @sa rfc4880:6.2 42 */ 43 unsigned char * 44 dearmor(char *pem, size_t nbytes, size_t *len) 45 { 46 #ifdef USE_BEARSSL 47 pem_object *po; 48 size_t npo; 49 #else 50 BIO *bp; 51 char *name = NULL; 52 char *header = NULL; 53 #endif 54 unsigned char *data = NULL; 55 char *cp; 56 char *ep; 57 58 /* we need to remove the Armor tail */ 59 if ((cp = strstr((char *)pem, "\n=")) && 60 (ep = strstr(cp, "\n---"))) { 61 memmove(cp, ep, nbytes - (size_t)(ep - pem)); 62 nbytes -= (size_t)(ep - cp); 63 pem[nbytes] = '\0'; 64 } 65 #ifdef USE_BEARSSL 66 /* we also need to remove any headers */ 67 if ((cp = strstr((char *)pem, "---\n")) && 68 (ep = strstr(cp, "\n\n"))) { 69 cp += 4; 70 ep += 2; 71 memmove(cp, ep, nbytes - (size_t)(ep - pem)); 72 nbytes -= (size_t)(ep - cp); 73 pem[nbytes] = '\0'; 74 } 75 if ((po = decode_pem(pem, nbytes, &npo))) { 76 data = po->data; 77 *len = po->data_len; 78 } 79 #else 80 if ((bp = BIO_new_mem_buf(pem, (int)nbytes))) { 81 long llen = (long)nbytes; 82 83 if (!PEM_read_bio(bp, &name, &header, &data, &llen)) 84 data = NULL; 85 BIO_free(bp); 86 *len = (size_t)llen; 87 } 88 #endif 89 return (data); 90 } 91 92 #ifdef MAIN_DEARMOR 93 #include <unistd.h> 94 #include <fcntl.h> 95 #include <err.h> 96 97 /* 98 * Mostly a unit test. 99 */ 100 int 101 main(int argc, char *argv[]) 102 { 103 const char *infile, *outfile; 104 unsigned char *data; 105 size_t n, x; 106 int fd; 107 int o; 108 109 infile = outfile = NULL; 110 while ((o = getopt(argc, argv, "i:o:")) != -1) { 111 switch (o) { 112 case 'i': 113 infile = optarg; 114 break; 115 case 'o': 116 outfile = optarg; 117 break; 118 default: 119 errx(1, "unknown option: -%c", o); 120 } 121 } 122 if (!infile) 123 errx(1, "need -i infile"); 124 if (outfile) { 125 if ((fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC)) < 0) 126 err(1, "cannot open %s", outfile); 127 } else { 128 fd = 1; /* stdout */ 129 } 130 data = read_file(infile, &n); 131 if (!(data[0] & OPENPGP_TAG_ISTAG)) 132 data = dearmor(data, n, &n); 133 for (x = 0; x < n; ) { 134 o = write(fd, &data[x], (n - x)); 135 if (o < 0) 136 err(1, "cannot write"); 137 x += o; 138 } 139 if (fd != 1) 140 close(fd); 141 free(data); 142 return (0); 143 } 144 #endif 145