1224090Sdougb/*
2254897Serwin * Copyright (C) 2006, 2008, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
3224090Sdougb *
4224090Sdougb * Permission to use, copy, modify, and/or distribute this software for any
5224090Sdougb * purpose with or without fee is hereby granted, provided that the above
6224090Sdougb * copyright notice and this permission notice appear in all copies.
7224090Sdougb *
8224090Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9224090Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10224090Sdougb * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11224090Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12224090Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13224090Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14224090Sdougb * PERFORMANCE OF THIS SOFTWARE.
15224090Sdougb */
16224090Sdougb
17254897Serwin/* $Id: nsec3hash.c,v 1.8 2011/11/02 23:46:24 tbox Exp $ */
18224090Sdougb
19224090Sdougb#include <config.h>
20224090Sdougb
21224090Sdougb#include <stdlib.h>
22224090Sdougb#include <stdarg.h>
23224090Sdougb
24224090Sdougb#include <isc/base32.h>
25224090Sdougb#include <isc/buffer.h>
26224090Sdougb#include <isc/hex.h>
27224090Sdougb#include <isc/iterated_hash.h>
28224090Sdougb#include <isc/print.h>
29224090Sdougb#include <isc/result.h>
30224090Sdougb#include <isc/string.h>
31224090Sdougb#include <isc/types.h>
32224090Sdougb
33224090Sdougb#include <dns/fixedname.h>
34224090Sdougb#include <dns/name.h>
35224090Sdougb#include <dns/nsec3.h>
36224090Sdougb#include <dns/types.h>
37224090Sdougb
38224090Sdougbconst char *program = "nsec3hash";
39224090Sdougb
40224090SdougbISC_PLATFORM_NORETURN_PRE static void
41224090Sdougbfatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
42224090Sdougb
43224090Sdougbstatic void
44224090Sdougbfatal(const char *format, ...) {
45224090Sdougb	va_list args;
46224090Sdougb
47224090Sdougb	fprintf(stderr, "%s: ", program);
48224090Sdougb	va_start(args, format);
49224090Sdougb	vfprintf(stderr, format, args);
50224090Sdougb	va_end(args);
51224090Sdougb	fprintf(stderr, "\n");
52224090Sdougb	exit(1);
53224090Sdougb}
54224090Sdougb
55224090Sdougbstatic void
56224090Sdougbcheck_result(isc_result_t result, const char *message) {
57224090Sdougb	if (result != ISC_R_SUCCESS)
58224090Sdougb		fatal("%s: %s", message, isc_result_totext(result));
59224090Sdougb}
60224090Sdougb
61224090Sdougbstatic void
62224090Sdougbusage() {
63234010Sdougb	printf("Usage: %s salt algorithm iterations domain\n", program);
64234010Sdougb	exit(1);
65224090Sdougb}
66224090Sdougb
67224090Sdougbint
68224090Sdougbmain(int argc, char **argv) {
69224090Sdougb	dns_fixedname_t fixed;
70224090Sdougb	dns_name_t *name;
71224090Sdougb	isc_buffer_t buffer;
72224090Sdougb	isc_region_t region;
73224090Sdougb	isc_result_t result;
74224090Sdougb	unsigned char hash[NSEC3_MAX_HASH_LENGTH];
75224090Sdougb	unsigned char salt[DNS_NSEC3_SALTSIZE];
76224090Sdougb	unsigned char text[1024];
77224090Sdougb	unsigned int hash_alg;
78224090Sdougb	unsigned int length;
79224090Sdougb	unsigned int iterations;
80224090Sdougb	unsigned int salt_length;
81224090Sdougb
82224090Sdougb	if (argc != 5)
83224090Sdougb		usage();
84224090Sdougb
85224090Sdougb	if (strcmp(argv[1], "-") == 0) {
86224090Sdougb		salt_length = 0;
87224090Sdougb		salt[0] = 0;
88224090Sdougb	} else {
89224090Sdougb		isc_buffer_init(&buffer, salt, sizeof(salt));
90224090Sdougb		result = isc_hex_decodestring(argv[1], &buffer);
91224090Sdougb		check_result(result, "isc_hex_decodestring(salt)");
92224090Sdougb		salt_length = isc_buffer_usedlength(&buffer);
93224090Sdougb		if (salt_length > DNS_NSEC3_SALTSIZE)
94224090Sdougb			fatal("salt too long");
95224090Sdougb	}
96224090Sdougb	hash_alg = atoi(argv[2]);
97224090Sdougb	if (hash_alg > 255U)
98224090Sdougb		fatal("hash algorithm too large");
99224090Sdougb	iterations = atoi(argv[3]);
100224090Sdougb	if (iterations > 0xffffU)
101224090Sdougb		fatal("iterations to large");
102224090Sdougb
103224090Sdougb	dns_fixedname_init(&fixed);
104224090Sdougb	name = dns_fixedname_name(&fixed);
105224090Sdougb	isc_buffer_init(&buffer, argv[4], strlen(argv[4]));
106224090Sdougb	isc_buffer_add(&buffer, strlen(argv[4]));
107224090Sdougb	result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL);
108224090Sdougb	check_result(result, "dns_name_fromtext() failed");
109224090Sdougb
110224090Sdougb	dns_name_downcase(name, name, NULL);
111224090Sdougb	length = isc_iterated_hash(hash, hash_alg, iterations,  salt,
112224090Sdougb				   salt_length, name->ndata, name->length);
113224090Sdougb	if (length == 0)
114224090Sdougb		fatal("isc_iterated_hash failed");
115224090Sdougb	region.base = hash;
116224090Sdougb	region.length = length;
117224090Sdougb	isc_buffer_init(&buffer, text, sizeof(text));
118224090Sdougb	isc_base32hex_totext(&region, 1, "", &buffer);
119224090Sdougb	fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n",
120224090Sdougb		(int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations);
121224090Sdougb	return(0);
122224090Sdougb}
123