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 "config.h" 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/param.h> 30 #include <sys/syslog.h> 31 32 #include <arpa/inet.h> 33 #include <ctype.h> 34 #include <inttypes.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <time.h> 40 #include <unistd.h> 41 42 #include "md5.h" 43 #include "rmd160.h" 44 #include "sha1.h" 45 #include "sha2.h" 46 47 #include "digest.h" 48 49 static uint8_t prefix_md5[] = { 50 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 51 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 52 }; 53 54 static uint8_t prefix_sha1[] = { 55 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 56 0x1A, 0x05, 0x00, 0x04, 0x14 57 }; 58 59 static uint8_t prefix_sha256[] = { 60 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 61 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 62 }; 63 64 static uint64_t prefix_tiger[] = { 65 0x0123456789ABCDEFLL, 66 0xFEDCBA9876543210LL, 67 0xF096A5B4C3B2E187LL 68 }; 69 70 static uint8_t prefix_rmd160[] = { 71 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 72 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 73 }; 74 75 static uint8_t prefix_sha512[] = { 76 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 77 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 78 }; 79 80 #define V4_SIGNATURE 4 81 82 /*************************************************************************/ 83 84 /* algorithm size (raw) */ 85 int 86 digest_alg_size(unsigned alg) 87 { 88 switch(alg) { 89 case MD5_HASH_ALG: 90 return 16; 91 case SHA1_HASH_ALG: 92 return 20; 93 case RIPEMD_HASH_ALG: 94 return RMD160_DIGEST_LENGTH; 95 case SHA256_HASH_ALG: 96 return 32; 97 case SHA512_HASH_ALG: 98 return 64; 99 case TIGER_HASH_ALG: 100 case TIGER2_HASH_ALG: 101 return TIGER_DIGEST_LENGTH; 102 default: 103 printf("hash_any: bad algorithm\n"); 104 return 0; 105 } 106 } 107 108 /* initialise the hash structure */ 109 int 110 digest_init(digest_t *hash, const uint32_t hashalg) 111 { 112 if (hash == NULL) { 113 return 0; 114 } 115 switch(hash->alg = hashalg) { 116 case MD5_HASH_ALG: 117 MD5Init(&hash->u.md5ctx); 118 hash->size = 16; 119 hash->prefix = prefix_md5; 120 hash->len = sizeof(prefix_md5); 121 hash->ctx = &hash->u.md5ctx; 122 return 1; 123 case SHA1_HASH_ALG: 124 SHA1Init(&hash->u.sha1ctx); 125 hash->size = 20; 126 hash->prefix = prefix_sha1; 127 hash->len = sizeof(prefix_sha1); 128 hash->ctx = &hash->u.sha1ctx; 129 return 1; 130 case RIPEMD_HASH_ALG: 131 RMD160Init(&hash->u.rmd160ctx); 132 hash->size = 20; 133 hash->prefix = prefix_rmd160; 134 hash->len = sizeof(prefix_rmd160); 135 hash->ctx = &hash->u.rmd160ctx; 136 return 1; 137 case SHA256_HASH_ALG: 138 SHA256_Init(&hash->u.sha256ctx); 139 hash->size = 32; 140 hash->prefix = prefix_sha256; 141 hash->len = sizeof(prefix_sha256); 142 hash->ctx = &hash->u.sha256ctx; 143 return 1; 144 case SHA512_HASH_ALG: 145 SHA512_Init(&hash->u.sha512ctx); 146 hash->size = 64; 147 hash->prefix = prefix_sha512; 148 hash->len = sizeof(prefix_sha512); 149 hash->ctx = &hash->u.sha512ctx; 150 return 1; 151 case TIGER_HASH_ALG: 152 TIGER_Init(&hash->u.tigerctx); 153 hash->size = TIGER_DIGEST_LENGTH; 154 hash->prefix = prefix_tiger; 155 hash->len = sizeof(prefix_tiger); 156 hash->ctx = &hash->u.tigerctx; 157 return 1; 158 case TIGER2_HASH_ALG: 159 TIGER2_Init(&hash->u.tigerctx); 160 hash->size = TIGER_DIGEST_LENGTH; 161 hash->prefix = prefix_tiger; 162 hash->len = sizeof(prefix_tiger); 163 hash->ctx = &hash->u.tigerctx; 164 return 1; 165 default: 166 printf("hash_any: bad algorithm\n"); 167 return 0; 168 } 169 } 170 171 typedef struct rec_t { 172 const char *s; 173 const unsigned alg; 174 } rec_t; 175 176 static rec_t hashalgs[] = { 177 { "md5", MD5_HASH_ALG }, 178 { "sha1", SHA1_HASH_ALG }, 179 { "ripemd", RIPEMD_HASH_ALG }, 180 { "sha256", SHA256_HASH_ALG }, 181 { "sha512", SHA512_HASH_ALG }, 182 { "tiger", TIGER_HASH_ALG }, 183 { "tiger2", TIGER2_HASH_ALG }, 184 { NULL, 0 } 185 }; 186 187 /* initialise by string alg name */ 188 unsigned 189 digest_get_alg(const char *hashalg) 190 { 191 rec_t *r; 192 193 for (r = hashalgs ; hashalg && r->s ; r++) { 194 if (strcasecmp(r->s, hashalg) == 0) { 195 return r->alg; 196 } 197 } 198 return 0; 199 } 200 201 int 202 digest_update(digest_t *hash, const uint8_t *data, size_t length) 203 { 204 if (hash == NULL || data == NULL) { 205 return 0; 206 } 207 switch(hash->alg) { 208 case MD5_HASH_ALG: 209 MD5Update(hash->ctx, data, (unsigned)length); 210 return 1; 211 case SHA1_HASH_ALG: 212 SHA1Update(hash->ctx, data, (unsigned)length); 213 return 1; 214 case RIPEMD_HASH_ALG: 215 RMD160Update(hash->ctx, data, (unsigned)length); 216 return 1; 217 case SHA256_HASH_ALG: 218 SHA256_Update(hash->ctx, data, length); 219 return 1; 220 case SHA512_HASH_ALG: 221 SHA512_Update(hash->ctx, data, length); 222 return 1; 223 case TIGER_HASH_ALG: 224 case TIGER2_HASH_ALG: 225 TIGER_Update(hash->ctx, data, length); 226 return 1; 227 default: 228 printf("hash_any: bad algorithm\n"); 229 return 0; 230 } 231 } 232 233 unsigned 234 digest_final(uint8_t *out, digest_t *hash) 235 { 236 if (hash == NULL || out == NULL) { 237 return 0; 238 } 239 switch(hash->alg) { 240 case MD5_HASH_ALG: 241 MD5Final(out, hash->ctx); 242 break; 243 case SHA1_HASH_ALG: 244 SHA1Final(out, hash->ctx); 245 break; 246 case RIPEMD_HASH_ALG: 247 RMD160Final(out, hash->ctx); 248 break; 249 case SHA256_HASH_ALG: 250 SHA256_Final(out, hash->ctx); 251 break; 252 case SHA512_HASH_ALG: 253 SHA512_Final(out, hash->ctx); 254 break; 255 case TIGER_HASH_ALG: 256 TIGER_Final(out, hash->ctx); 257 break; 258 default: 259 printf("hash_any: bad algorithm\n"); 260 return 0; 261 } 262 (void) memset(hash->ctx, 0x0, hash->size); 263 return (unsigned)hash->size; 264 } 265 266 int 267 digest_length(digest_t *hash, unsigned hashedlen) 268 { 269 uint8_t trailer[6]; 270 271 if (hash == NULL) { 272 return 0; 273 } 274 trailer[0] = V4_SIGNATURE; 275 trailer[1] = 0xFF; 276 trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff); 277 trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff); 278 trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff); 279 trailer[5] = (uint8_t)(hashedlen & 0xff); 280 digest_update(hash, trailer, sizeof(trailer)); 281 return 1; 282 } 283 284 unsigned 285 digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size) 286 { 287 USE_ARG(size); 288 if (prefix == NULL) { 289 return 0; 290 } 291 switch (hashalg) { 292 case MD5_HASH_ALG: 293 memcpy(prefix, prefix_md5, sizeof(prefix_md5)); 294 return sizeof(prefix_md5); 295 case SHA1_HASH_ALG: 296 memcpy(prefix, prefix_sha1, sizeof(prefix_sha1)); 297 return sizeof(prefix_sha1); 298 case SHA256_HASH_ALG: 299 memcpy(prefix, prefix_sha256, sizeof(prefix_sha256)); 300 return sizeof(prefix_sha256); 301 default: 302 printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg); 303 return 0; 304 } 305 } 306 307