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