/** * Create NSEC3 salt. * */ ods_status nsec3params_create_salt(const char* salt_str, uint8_t* salt_len, uint8_t** salt) { uint8_t c; uint8_t* salt_tmp; if (!salt_str) { *salt_len = 0; *salt = NULL; return ODS_STATUS_OK; } *salt_len = (uint8_t) strlen(salt_str); if (*salt_len == 1 && salt_str[0] == '-') { *salt_len = 0; *salt = NULL; return ODS_STATUS_OK; } else if (*salt_len % 2 != 0) { ods_log_error("[%s] invalid salt %s", nsec3_str, salt_str); *salt = NULL; return ODS_STATUS_ERR; } /* construct salt data */ salt_tmp = (uint8_t*) calloc(*salt_len / 2, sizeof(uint8_t)); if (!salt_tmp) { ods_log_error("[%s] construct salt data for %s failed", nsec3_str, salt_str); *salt = NULL; return ODS_STATUS_MALLOC_ERR; } for (c = 0; c < *salt_len; c += 2) { if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { salt_tmp[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + ldns_hexdigit_to_int(salt_str[c+1]); } else { ods_log_error("[%s] invalid salt %s", nsec3_str, salt_str); free((void*)salt_tmp); *salt = NULL; return ODS_STATUS_ERR; } } *salt_len = *salt_len / 2; /* update length */ *salt = salt_tmp; return ODS_STATUS_OK; }
int ldns_hexstring_to_data(uint8_t *data, const char *str) { unsigned int i; if (!str || !data) { return -1; } if (strlen(str) % 2 != 0) { return -2; } for (i = 0; i < strlen(str) / 2; i++) { data[i] = 16 * ldns_hexdigit_to_int(str[i*2]) + ldns_hexdigit_to_int(str[i*2 + 1]); } return (int) i; }
int main(int argc, char *argv[]) { ldns_rdf *dname, *hashed_dname; uint8_t nsec3_algorithm = 1; size_t nsec3_iterations_cmd = 1; uint16_t nsec3_iterations = 1; uint8_t nsec3_salt_length = 0; uint8_t *nsec3_salt = NULL; char *prog = strdup(argv[0]); int c; while ((c = getopt(argc, argv, "a:s:t:")) != -1) { switch (c) { case 'a': nsec3_algorithm = (uint8_t) atoi(optarg); break; case 's': if (strlen(optarg) % 2 != 0) { fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n"); exit(EXIT_FAILURE); } if (strlen(optarg) > 512) { fprintf(stderr, "Salt too long\n"); exit(EXIT_FAILURE); } nsec3_salt_length = (uint8_t) (strlen(optarg) / 2); nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length); for (c = 0; c < (int) strlen(optarg); c += 2) { if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) { nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 + ldns_hexdigit_to_int(optarg[c+1]); } else { fprintf(stderr, "Salt value is not valid hex data.\n"); exit(EXIT_FAILURE); } } break; case 't': nsec3_iterations_cmd = (size_t) atol(optarg); if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) { fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS); exit(EXIT_FAILURE); } nsec3_iterations = (uint16_t) nsec3_iterations_cmd; break; default: usage(stderr, prog); exit(EXIT_SUCCESS); } } argc -= optind; argv += optind; if (argc < 1) { printf("Error: not enough arguments\n"); usage(stdout, prog); exit(EXIT_FAILURE); } else { dname = ldns_dname_new_frm_str(argv[0]); if (!dname) { fprintf(stderr, "Error: unable to parse domain name\n"); return EXIT_FAILURE; } hashed_dname = ldns_nsec3_hash_name(dname, nsec3_algorithm, nsec3_iterations, nsec3_salt_length, nsec3_salt); if (!hashed_dname) { fprintf(stderr, "Error creating NSEC3 hash\n"); return EXIT_FAILURE; } ldns_rdf_print(stdout, hashed_dname); printf("\n"); ldns_rdf_deep_free(dname); ldns_rdf_deep_free(hashed_dname); } if (nsec3_salt) { free(nsec3_salt); } free(prog); return EXIT_SUCCESS; }