1/*
2 * Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: isc-hmac-fixup.c,v 1.4 2010/03/10 02:17:52 marka Exp $ */
18
19#include <config.h>
20
21#include <isc/base64.h>
22#include <isc/buffer.h>
23#include <isc/md5.h>
24#include <isc/region.h>
25#include <isc/result.h>
26#include <isc/sha1.h>
27#include <isc/sha2.h>
28#include <isc/stdio.h>
29#include <isc/string.h>
30
31#define HMAC_LEN	64
32
33int
34main(int argc, char **argv)  {
35	isc_buffer_t buf;
36	unsigned char key[1024];
37	char secret[1024];
38	char base64[(1024*4)/3];
39	isc_region_t r;
40	isc_result_t result;
41
42	if (argc != 3) {
43		fprintf(stderr, "Usage:\t%s algorithm secret\n", argv[0]);
44		fprintf(stderr, "\talgorithm: (MD5 | SHA1 | SHA224 | "
45				"SHA256 | SHA384 | SHA512)\n");
46		return (1);
47	}
48
49	isc_buffer_init(&buf, secret, sizeof(secret));
50	result = isc_base64_decodestring(argv[2], &buf);
51	if (result != ISC_R_SUCCESS) {
52		fprintf(stderr, "error: %s\n", isc_result_totext(result));
53		return (1);
54	}
55	isc__buffer_usedregion(&buf, &r);
56
57	if (!strcasecmp(argv[1], "md5") ||
58	    !strcasecmp(argv[1], "hmac-md5")) {
59		if (r.length > HMAC_LEN) {
60			isc_md5_t md5ctx;
61			isc_md5_init(&md5ctx);
62			isc_md5_update(&md5ctx, r.base, r.length);
63			isc_md5_final(&md5ctx, key);
64
65			r.base = key;
66			r.length = ISC_MD5_DIGESTLENGTH;
67		}
68	} else if (!strcasecmp(argv[1], "sha1") ||
69		   !strcasecmp(argv[1], "hmac-sha1")) {
70		if (r.length > ISC_SHA1_DIGESTLENGTH) {
71			isc_sha1_t sha1ctx;
72			isc_sha1_init(&sha1ctx);
73			isc_sha1_update(&sha1ctx, r.base, r.length);
74			isc_sha1_final(&sha1ctx, key);
75
76			r.base = key;
77			r.length = ISC_SHA1_DIGESTLENGTH;
78		}
79	} else if (!strcasecmp(argv[1], "sha224") ||
80		   !strcasecmp(argv[1], "hmac-sha224")) {
81		if (r.length > ISC_SHA224_DIGESTLENGTH) {
82			isc_sha224_t sha224ctx;
83			isc_sha224_init(&sha224ctx);
84			isc_sha224_update(&sha224ctx, r.base, r.length);
85			isc_sha224_final(key, &sha224ctx);
86
87			r.base = key;
88			r.length = ISC_SHA224_DIGESTLENGTH;
89		}
90	} else if (!strcasecmp(argv[1], "sha256") ||
91		   !strcasecmp(argv[1], "hmac-sha256")) {
92		if (r.length > ISC_SHA256_DIGESTLENGTH) {
93			isc_sha256_t sha256ctx;
94			isc_sha256_init(&sha256ctx);
95			isc_sha256_update(&sha256ctx, r.base, r.length);
96			isc_sha256_final(key, &sha256ctx);
97
98			r.base = key;
99			r.length = ISC_SHA256_DIGESTLENGTH;
100		}
101	} else if (!strcasecmp(argv[1], "sha384") ||
102		   !strcasecmp(argv[1], "hmac-sha384")) {
103		if (r.length > ISC_SHA384_DIGESTLENGTH) {
104			isc_sha384_t sha384ctx;
105			isc_sha384_init(&sha384ctx);
106			isc_sha384_update(&sha384ctx, r.base, r.length);
107			isc_sha384_final(key, &sha384ctx);
108
109			r.base = key;
110			r.length = ISC_SHA384_DIGESTLENGTH;
111		}
112	} else if (!strcasecmp(argv[1], "sha512") ||
113		   !strcasecmp(argv[1], "hmac-sha512")) {
114		if (r.length > ISC_SHA512_DIGESTLENGTH) {
115			isc_sha512_t sha512ctx;
116			isc_sha512_init(&sha512ctx);
117			isc_sha512_update(&sha512ctx, r.base, r.length);
118			isc_sha512_final(key, &sha512ctx);
119
120			r.base = key;
121			r.length = ISC_SHA512_DIGESTLENGTH;
122		}
123	} else {
124		fprintf(stderr, "unknown hmac/digest algorithm: %s\n", argv[1]);
125		return (1);
126	}
127
128	isc_buffer_init(&buf, base64, sizeof(base64));
129	result = isc_base64_totext(&r, 0, "", &buf);
130	if (result != ISC_R_SUCCESS) {
131		fprintf(stderr, "error: %s\n", isc_result_totext(result));
132		return (1);
133	}
134	fprintf(stdout, "%.*s\n", (int)isc_buffer_usedlength(&buf), base64);
135	return (0);
136}
137