1 /* 2 * Copyright (c) 2019 The DragonFly Project. All rights reserved. 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 16 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 17 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 23 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <openssl/md5.h> 34 #include <openssl/sha.h> 35 #include <openssl/ripemd.h> 36 37 #include <stdio.h> /* for FILE in mtree.h */ 38 #include "extern.h" 39 40 /* max(MD5_DIGEST_LENGTH, SHA_DIGEST_LENGTH, 41 SHA256_DIGEST_LENGTH, SHA512_DIGEST_LENGTH, 42 RIPEMD160_DIGEST_LENGTH) * 2 + 1 */ 43 #define HEX_DIGEST_LENGTH 129 44 45 typedef union { 46 MD5_CTX md5; 47 SHA_CTX sha1; 48 SHA256_CTX sha256; 49 SHA512_CTX sha512; 50 RIPEMD160_CTX ripemd160; 51 } DIGEST_CTX; 52 53 char * 54 dohash(int flag, const char *filename) 55 { 56 unsigned char digest[HEX_DIGEST_LENGTH]; 57 static const char hex[]="0123456789abcdef"; 58 DIGEST_CTX context; 59 void *ctx; 60 unsigned char buffer[4096]; 61 char *buf; 62 struct stat st; 63 off_t size; 64 int fd, bytes, i, digest_len; 65 66 ctx = &context; 67 68 if (flag == F_MD5) 69 digest_len = MD5_DIGEST_LENGTH; 70 else if (flag == F_RMD160) 71 digest_len = RIPEMD160_DIGEST_LENGTH; 72 else if (flag == F_SHA1) 73 digest_len = SHA_DIGEST_LENGTH; 74 else if (flag == F_SHA256) 75 digest_len = SHA256_DIGEST_LENGTH; 76 else if (flag == F_SHA384) 77 digest_len = SHA384_DIGEST_LENGTH; 78 else if (flag == F_SHA512) 79 digest_len = SHA512_DIGEST_LENGTH; 80 else 81 return NULL; 82 83 buf = malloc(digest_len * 2 + 1); 84 if (!buf) 85 return NULL; 86 87 fd = open(filename, O_RDONLY); 88 if (fd < 0) 89 return NULL; 90 if (fstat(fd, &st) < 0) { 91 bytes = -1; 92 goto err; 93 } 94 95 if (flag == F_MD5) 96 MD5_Init(ctx); 97 else if (flag == F_RMD160) 98 RIPEMD160_Init(ctx); 99 else if (flag == F_SHA1) 100 SHA1_Init(ctx); 101 else if (flag == F_SHA256) 102 SHA256_Init(ctx); 103 else if (flag == F_SHA384) 104 SHA384_Init(ctx); 105 else if (flag == F_SHA512) 106 SHA512_Init(ctx); 107 108 size = st.st_size; 109 bytes = 0; 110 while (size > 0) { 111 if ((size_t)size > sizeof(buffer)) 112 bytes = read(fd, buffer, sizeof(buffer)); 113 else 114 bytes = read(fd, buffer, size); 115 if (bytes < 0) 116 break; 117 118 if (flag == F_MD5) 119 MD5_Update(ctx, buffer, bytes); 120 else if (flag == F_RMD160) 121 RIPEMD160_Update(ctx, buffer, bytes); 122 else if (flag == F_SHA1) 123 SHA1_Update(ctx, buffer, bytes); 124 else if (flag == F_SHA256) 125 SHA256_Update(ctx, buffer, bytes); 126 else if (flag == F_SHA384) 127 SHA384_Update(ctx, buffer, bytes); 128 else if (flag == F_SHA512) 129 SHA512_Update(ctx, buffer, bytes); 130 131 size -= bytes; 132 } 133 134 err: 135 close(fd); 136 137 if (bytes < 0) 138 return NULL; 139 140 if (flag == F_MD5) 141 MD5_Final(digest, ctx); 142 else if (flag == F_RMD160) 143 RIPEMD160_Final(digest, ctx); 144 else if (flag == F_SHA1) 145 SHA1_Final(digest, ctx); 146 else if (flag == F_SHA256) 147 SHA256_Final(digest, ctx); 148 else if (flag == F_SHA384) 149 SHA384_Final(digest, ctx); 150 else if (flag == F_SHA512) 151 SHA512_Final(digest, ctx); 152 153 for (i = 0; i < digest_len; i++) { 154 buf[2*i] = hex[digest[i] >> 4]; 155 buf[2*i+1] = hex[digest[i] & 0x0f]; 156 } 157 buf[digest_len * 2] = '\0'; 158 159 return buf; 160 } 161