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