1/*- 2 * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT 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 OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <sys/mman.h> 28 29#include <err.h> 30#include <inttypes.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <unistd.h> 35
| 1/*- 2 * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT 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 OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <sys/mman.h> 28 29#include <err.h> 30#include <inttypes.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <unistd.h> 35
|
36#include "digest.h"
| 36#include <netpgp/digest.h> 37
|
37#include "pgpsum.h" 38
| 38#include "pgpsum.h" 39
|
39#ifndef USE_ARG 40#define USE_ARG(x) /*LINTED*/(void)&(x) 41#endif 42
| |
43/* add the ascii armor line endings (except for last line) */ 44static size_t
| 40/* add the ascii armor line endings (except for last line) */ 41static size_t
|
45don_armor(digest_t *hash, uint8_t *in, size_t insize, int doarmor)
| 42don_armor(digest_t *hash, uint8_t *in, size_t insize)
|
46{ 47 uint8_t *from;
| 43{ 44 uint8_t *from;
|
48 uint8_t *newp;
| |
49 uint8_t *p; 50 uint8_t dos_line_end[2]; 51 52 dos_line_end[0] = '\r'; 53 dos_line_end[1] = '\n'; 54 for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) {
| 45 uint8_t *p; 46 uint8_t dos_line_end[2]; 47 48 dos_line_end[0] = '\r'; 49 dos_line_end[1] = '\n'; 50 for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) {
|
55 for (newp = p ; doarmor == 'w' && newp > from ; --newp) { 56 if (*(newp - 1) != ' ' && *(newp - 1) != '\t') { 57 break; 58 } 59 } 60 digest_update(hash, from, (size_t)(newp - from));
| 51 digest_update(hash, from, (size_t)(p - from));
|
61 digest_update(hash, dos_line_end, sizeof(dos_line_end)); 62 } 63 digest_update(hash, from, insize - (size_t)(from - in)); 64 return 1; 65} 66 67#ifdef NETPGPV_DEBUG 68/* just for giggles, write what we're about to checksum */ 69static int 70writefile(uint8_t *mem, size_t insize) 71{ 72 size_t cc; 73 size_t wc; 74 char template[256]; 75 int fd; 76 77 snprintf(template, sizeof(template), "netpgpvmd.XXXXXX"); 78 if ((fd = mkstemp(template)) < 0) { 79 fprintf(stderr, "can't mkstemp %s\n", template); 80 return 0; 81 } 82 for (cc = 0 ; cc < insize ; cc += wc) { 83 if ((wc = write(fd, &mem[cc], insize - cc)) <= 0) { 84 fprintf(stderr, "short write\n"); 85 break; 86 } 87 } 88 close(fd); 89 return 1; 90} 91#endif 92 93/* return non-zero if this is actually an armored piece already */ 94static int 95already_armored(uint8_t *in, size_t insize) 96{ 97 uint8_t *from; 98 uint8_t *p; 99 100 for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) { 101 if (*(p - 1) != '\r') { 102 return 0; 103 } 104 } 105 return 1; 106} 107 108/* calculate the checksum for the data we have */ 109static int
| 52 digest_update(hash, dos_line_end, sizeof(dos_line_end)); 53 } 54 digest_update(hash, from, insize - (size_t)(from - in)); 55 return 1; 56} 57 58#ifdef NETPGPV_DEBUG 59/* just for giggles, write what we're about to checksum */ 60static int 61writefile(uint8_t *mem, size_t insize) 62{ 63 size_t cc; 64 size_t wc; 65 char template[256]; 66 int fd; 67 68 snprintf(template, sizeof(template), "netpgpvmd.XXXXXX"); 69 if ((fd = mkstemp(template)) < 0) { 70 fprintf(stderr, "can't mkstemp %s\n", template); 71 return 0; 72 } 73 for (cc = 0 ; cc < insize ; cc += wc) { 74 if ((wc = write(fd, &mem[cc], insize - cc)) <= 0) { 75 fprintf(stderr, "short write\n"); 76 break; 77 } 78 } 79 close(fd); 80 return 1; 81} 82#endif 83 84/* return non-zero if this is actually an armored piece already */ 85static int 86already_armored(uint8_t *in, size_t insize) 87{ 88 uint8_t *from; 89 uint8_t *p; 90 91 for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) { 92 if (*(p - 1) != '\r') { 93 return 0; 94 } 95 } 96 return 1; 97} 98 99/* calculate the checksum for the data we have */ 100static int
|
110calcsum(uint8_t *out, size_t size, uint8_t *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor)
| 101calcsum(uint8_t *out, size_t size, const char *name, uint8_t *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor)
|
111{ 112 digest_t hash; 113 uint32_t len32; 114 uint16_t len16; 115 uint8_t hashalg; 116 uint8_t trailer[6]; 117
| 102{ 103 digest_t hash; 104 uint32_t len32; 105 uint16_t len16; 106 uint8_t hashalg; 107 uint8_t trailer[6]; 108
|
118 USE_ARG(size);
| |
119 /* hashed data is non-null (previously checked) */ 120 hashalg = hashed[3]; 121 memcpy(&len16, &hashed[4], sizeof(len16)); 122 len32 = ntohs(len16) + 6; 123 len32 = htonl(len32); 124 trailer[0] = 0x04; 125 trailer[1] = 0xff; 126 memcpy(&trailer[2], &len32, sizeof(len32)); 127#ifdef NETPGPV_DEBUG 128 writefile(mem, cc); 129#endif
| 109 /* hashed data is non-null (previously checked) */ 110 hashalg = hashed[3]; 111 memcpy(&len16, &hashed[4], sizeof(len16)); 112 len32 = ntohs(len16) + 6; 113 len32 = htonl(len32); 114 trailer[0] = 0x04; 115 trailer[1] = 0xff; 116 memcpy(&trailer[2], &len32, sizeof(len32)); 117#ifdef NETPGPV_DEBUG 118 writefile(mem, cc); 119#endif
|
130 digest_init(&hash, (const unsigned)hashalg); 131 if (strchr("tw", doarmor) != NULL && !already_armored(mem, cc)) {
| 120 digest_init(&hash, hashalg); 121 if (doarmor && !already_armored(mem, cc)) {
|
132 /* this took me ages to find - something causes gpg to truncate its input */
| 122 /* this took me ages to find - something causes gpg to truncate its input */
|
133 don_armor(&hash, mem, cc - 1, doarmor);
| 123 don_armor(&hash, mem, cc - 1);
|
134 } else { 135 digest_update(&hash, mem, cc); 136 } 137 if (hashed) { 138 digest_update(&hash, hashed, hashsize); 139 } 140 digest_update(&hash, trailer, sizeof(trailer)); 141 return digest_final(out, &hash); 142} 143 144/* open the file, mmap it, and then get the checksum on that */ 145int 146pgpv_digest_file(uint8_t *data, size_t size, const char *name, const uint8_t *hashed, size_t hashsize, int doarmor) 147{ 148 struct stat st; 149 uint8_t *mem; 150 size_t cc; 151 FILE *fp; 152 int ret; 153 154 if (hashed == NULL || data == NULL || name == NULL) { 155 fprintf(stderr, "no hashed data provided\n"); 156 return 0; 157 } 158 ret = 0; 159 mem = NULL; 160 cc = 0; 161 if ((fp = fopen(name, "r")) == NULL) { 162 warn("%s - not found", name); 163 return 0; 164 } 165 if (fstat(fileno(fp), &st) < 0) { 166 warn("%s - can't stat", name); 167 goto done; 168 } 169 cc = (size_t)(st.st_size); 170 if ((mem = mmap(NULL, cc, PROT_READ, MAP_SHARED, fileno(fp), 0)) == MAP_FAILED) { 171 warn("%s - can't mmap", name); 172 goto done; 173 }
| 124 } else { 125 digest_update(&hash, mem, cc); 126 } 127 if (hashed) { 128 digest_update(&hash, hashed, hashsize); 129 } 130 digest_update(&hash, trailer, sizeof(trailer)); 131 return digest_final(out, &hash); 132} 133 134/* open the file, mmap it, and then get the checksum on that */ 135int 136pgpv_digest_file(uint8_t *data, size_t size, const char *name, const uint8_t *hashed, size_t hashsize, int doarmor) 137{ 138 struct stat st; 139 uint8_t *mem; 140 size_t cc; 141 FILE *fp; 142 int ret; 143 144 if (hashed == NULL || data == NULL || name == NULL) { 145 fprintf(stderr, "no hashed data provided\n"); 146 return 0; 147 } 148 ret = 0; 149 mem = NULL; 150 cc = 0; 151 if ((fp = fopen(name, "r")) == NULL) { 152 warn("%s - not found", name); 153 return 0; 154 } 155 if (fstat(fileno(fp), &st) < 0) { 156 warn("%s - can't stat", name); 157 goto done; 158 } 159 cc = (size_t)(st.st_size); 160 if ((mem = mmap(NULL, cc, PROT_READ, MAP_SHARED, fileno(fp), 0)) == MAP_FAILED) { 161 warn("%s - can't mmap", name); 162 goto done; 163 }
|
174 ret = calcsum(data, size, mem, cc, hashed, hashsize, doarmor);
| 164 ret = calcsum(data, size, name, mem, cc, hashed, hashsize, doarmor);
|
175done: 176 if (data) { 177 munmap(mem, cc); 178 } 179 fclose(fp); 180 return ret; 181} 182 183/* calculate the digest over memory too */ 184int 185pgpv_digest_memory(uint8_t *data, size_t size, void *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor) 186{ 187 if (hashed == NULL || data == NULL || mem == NULL) { 188 fprintf(stderr, "no hashed data provided\n"); 189 return 0; 190 }
| 165done: 166 if (data) { 167 munmap(mem, cc); 168 } 169 fclose(fp); 170 return ret; 171} 172 173/* calculate the digest over memory too */ 174int 175pgpv_digest_memory(uint8_t *data, size_t size, void *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor) 176{ 177 if (hashed == NULL || data == NULL || mem == NULL) { 178 fprintf(stderr, "no hashed data provided\n"); 179 return 0; 180 }
|
191 return calcsum(data, size, mem, cc, hashed, hashsize, doarmor);
| 181 return calcsum(data, size, "[memory]", mem, cc, hashed, hashsize, doarmor);
|
192}
| 182}
|