/*- * Copyright (c) 2012 Alistair Crooks * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "md5.h" #include "rmd160.h" #include "sha1.h" #include "sha2.h" #include "digest.h" #ifndef USE_ARG #define USE_ARG(x) /*LINTED*/(void)&(x) #endif static uint8_t prefix_md5[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; static uint8_t prefix_sha1[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 }; static uint8_t prefix_sha256[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; static uint8_t prefix_rmd160[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; static uint8_t prefix_sha512[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; #define V4_SIGNATURE 4 /*************************************************************************/ /* algorithm size (raw) */ int digest_alg_size(unsigned alg) { switch(alg) { case MD5_HASH_ALG: return 16; case SHA1_HASH_ALG: return 20; case RIPEMD_HASH_ALG: return RMD160_DIGEST_LENGTH; case SHA256_HASH_ALG: return 32; case SHA512_HASH_ALG: return 64; default: printf("hash_any: bad algorithm\n"); return 0; } } /* initialise the hash structure */ int digest_init(digest_t *hash, const uint32_t hashalg) { if (hash == NULL) { return 0; } switch(hash->alg = hashalg) { case MD5_HASH_ALG: netpgpv_MD5Init(&hash->u.md5ctx); hash->size = 16; hash->prefix = prefix_md5; hash->len = sizeof(prefix_md5); hash->ctx = &hash->u.md5ctx; return 1; case SHA1_HASH_ALG: netpgpv_SHA1Init(&hash->u.sha1ctx); hash->size = 20; hash->prefix = prefix_sha1; hash->len = sizeof(prefix_sha1); hash->ctx = &hash->u.sha1ctx; return 1; case RIPEMD_HASH_ALG: netpgpv_RMD160Init(&hash->u.rmd160ctx); hash->size = 20; hash->prefix = prefix_rmd160; hash->len = sizeof(prefix_rmd160); hash->ctx = &hash->u.rmd160ctx; return 1; case SHA256_HASH_ALG: netpgpv_SHA256_Init(&hash->u.sha256ctx); hash->size = 32; hash->prefix = prefix_sha256; hash->len = sizeof(prefix_sha256); hash->ctx = &hash->u.sha256ctx; return 1; case SHA512_HASH_ALG: netpgpv_SHA512_Init(&hash->u.sha512ctx); hash->size = 64; hash->prefix = prefix_sha512; hash->len = sizeof(prefix_sha512); hash->ctx = &hash->u.sha512ctx; return 1; default: printf("hash_any: bad algorithm\n"); return 0; } } typedef struct rec_t { const char *s; const unsigned alg; } rec_t; static rec_t hashalgs[] = { { "md5", MD5_HASH_ALG }, { "sha1", SHA1_HASH_ALG }, { "ripemd", RIPEMD_HASH_ALG }, { "sha256", SHA256_HASH_ALG }, { "sha512", SHA512_HASH_ALG }, { NULL, 0 } }; /* initialise by string alg name */ unsigned digest_get_alg(const char *hashalg) { rec_t *r; for (r = hashalgs ; hashalg && r->s ; r++) { if (strcasecmp(r->s, hashalg) == 0) { return r->alg; } } return 0; } int digest_update(digest_t *hash, const uint8_t *data, size_t length) { if (hash == NULL || data == NULL) { return 0; } switch(hash->alg) { case MD5_HASH_ALG: netpgpv_MD5Update(hash->ctx, data, (unsigned)length); return 1; case SHA1_HASH_ALG: netpgpv_SHA1Update(hash->ctx, data, (unsigned)length); return 1; case RIPEMD_HASH_ALG: netpgpv_RMD160Update(hash->ctx, data, (unsigned)length); return 1; case SHA256_HASH_ALG: netpgpv_SHA256_Update(hash->ctx, data, length); return 1; case SHA512_HASH_ALG: netpgpv_SHA512_Update(hash->ctx, data, length); return 1; default: printf("hash_any: bad algorithm\n"); return 0; } } unsigned digest_final(uint8_t *out, digest_t *hash) { if (hash == NULL || out == NULL) { return 0; } switch(hash->alg) { case MD5_HASH_ALG: netpgpv_MD5Final(out, hash->ctx); break; case SHA1_HASH_ALG: netpgpv_SHA1Final(out, hash->ctx); break; case RIPEMD_HASH_ALG: netpgpv_RMD160Final(out, hash->ctx); break; case SHA256_HASH_ALG: netpgpv_SHA256_Final(out, hash->ctx); break; case SHA512_HASH_ALG: netpgpv_SHA512_Final(out, hash->ctx); break; default: printf("hash_any: bad algorithm\n"); return 0; } (void) memset(hash->ctx, 0x0, hash->size); return (unsigned)hash->size; } int digest_length(digest_t *hash, unsigned hashedlen) { uint8_t trailer[6]; if (hash == NULL) { return 0; } trailer[0] = V4_SIGNATURE; trailer[1] = 0xFF; trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff); trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff); trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff); trailer[5] = (uint8_t)(hashedlen & 0xff); digest_update(hash, trailer, sizeof(trailer)); return 1; } unsigned digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size) { USE_ARG(size); if (prefix == NULL) { return 0; } switch (hashalg) { case MD5_HASH_ALG: memcpy(prefix, prefix_md5, sizeof(prefix_md5)); return sizeof(prefix_md5); case SHA1_HASH_ALG: memcpy(prefix, prefix_sha1, sizeof(prefix_sha1)); return sizeof(prefix_sha1); case SHA256_HASH_ALG: memcpy(prefix, prefix_sha256, sizeof(prefix_sha256)); return sizeof(prefix_sha256); case SHA512_HASH_ALG: memcpy(prefix, prefix_sha512, sizeof(prefix_sha512)); return sizeof(prefix_sha512); default: printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg); return 0; } }