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 #define NEED_BRSSL_H 28 #include <libsecureboot.h> 29 #include <brssl.h> 30 31 #include "decode.h" 32 33 /** 34 * @brief decode ascii armor 35 * 36 * once we get rid of the trailing checksum 37 * we can treat as PEM. 38 * 39 * @sa rfc4880:6.2 40 */ 41 unsigned char * 42 dearmor(char *pem, size_t nbytes, size_t *len) 43 { 44 #ifdef USE_BEARSSL 45 pem_object *po; 46 size_t npo; 47 #else 48 BIO *bp; 49 char *name = NULL; 50 char *header = NULL; 51 #endif 52 unsigned char *data = NULL; 53 char *cp; 54 char *ep; 55 56 /* we need to remove the Armor tail */ 57 if ((cp = strstr((char *)pem, "\n=")) && 58 (ep = strstr(cp, "\n---"))) { 59 memmove(cp, ep, nbytes - (size_t)(ep - pem)); 60 nbytes -= (size_t)(ep - cp); 61 pem[nbytes] = '\0'; 62 } 63 #ifdef USE_BEARSSL 64 /* we also need to remove any headers */ 65 if ((cp = strstr((char *)pem, "---\n")) && 66 (ep = strstr(cp, "\n\n"))) { 67 cp += 4; 68 ep += 2; 69 memmove(cp, ep, nbytes - (size_t)(ep - pem)); 70 nbytes -= (size_t)(ep - cp); 71 pem[nbytes] = '\0'; 72 } 73 if ((po = decode_pem(pem, nbytes, &npo))) { 74 data = po->data; 75 *len = po->data_len; 76 } 77 #else 78 if ((bp = BIO_new_mem_buf(pem, (int)nbytes))) { 79 long llen = (long)nbytes; 80 81 if (!PEM_read_bio(bp, &name, &header, &data, &llen)) 82 data = NULL; 83 BIO_free(bp); 84 *len = (size_t)llen; 85 } 86 #endif 87 return (data); 88 } 89 90 #ifdef MAIN_DEARMOR 91 #include <unistd.h> 92 #include <fcntl.h> 93 #include <err.h> 94 95 /* 96 * Mostly a unit test. 97 */ 98 int 99 main(int argc, char *argv[]) 100 { 101 const char *infile, *outfile; 102 unsigned char *data; 103 size_t n, x; 104 int fd; 105 int o; 106 107 infile = outfile = NULL; 108 while ((o = getopt(argc, argv, "i:o:")) != -1) { 109 switch (o) { 110 case 'i': 111 infile = optarg; 112 break; 113 case 'o': 114 outfile = optarg; 115 break; 116 default: 117 errx(1, "unknown option: -%c", o); 118 } 119 } 120 if (!infile) 121 errx(1, "need -i infile"); 122 if (outfile) { 123 if ((fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC)) < 0) 124 err(1, "cannot open %s", outfile); 125 } else { 126 fd = 1; /* stdout */ 127 } 128 data = read_file(infile, &n); 129 if (!(data[0] & OPENPGP_TAG_ISTAG)) 130 data = dearmor(data, n, &n); 131 for (x = 0; x < n; ) { 132 o = write(fd, &data[x], (n - x)); 133 if (o < 0) 134 err(1, "cannot write"); 135 x += o; 136 } 137 if (fd != 1) 138 close(fd); 139 free(data); 140 return (0); 141 } 142 #endif 143