static void dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx) { dst_key_t *key1 = NULL, *key2 = NULL; isc_result_t ret; isc_buffer_t b1, b2; isc_region_t r1, r2; unsigned char array1[1024], array2[1024]; int alg = DST_ALG_DH; int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key1, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key2, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b1, array1, sizeof(array1)); ret = dst_key_computesecret(key1, key2, &b1); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b2, array2, sizeof(array2)); ret = dst_key_computesecret(key2, key1, &b2); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_usedregion(&b1, &r1); isc_buffer_usedregion(&b2, &r2); if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0) { int i; printf("secrets don't match\n"); printf("secret 1: %d bytes\n", r1.length); for (i = 0; i < (int) r1.length; i++) printf("%02x ", r1.base[i]); printf("\n"); printf("secret 2: %d bytes\n", r2.length); for (i = 0; i < (int) r2.length; i++) printf("%02x ", r2.base[i]); printf("\n"); } dst_key_free(&key1); dst_key_free(&key2); }
static void recvquery(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; dns_message_t *query, *response; char keyname[256]; isc_buffer_t keynamebuf; int type; UNUSED(task); REQUIRE(reqev != NULL); if (reqev->result != ISC_R_SUCCESS) { fprintf(stderr, "I:request event result: %s\n", isc_result_totext(reqev->result)); exit(-1); } query = reqev->ev_arg; response = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); CHECK("dns_message_create", result); result = dns_request_getresponse(reqev->request, response, DNS_MESSAGEPARSE_PRESERVEORDER); CHECK("dns_request_getresponse", result); if (response->rcode != dns_rcode_noerror) { result = ISC_RESULTCLASS_DNSRCODE + response->rcode; fprintf(stderr, "I:response rcode: %s\n", isc_result_totext(result)); exit(-1); } result = dns_tkey_processdhresponse(query, response, ourkey, &nonce, &tsigkey, ring); CHECK("dns_tkey_processdhresponse", result); /* * Yes, this is a hack. */ isc_buffer_init(&keynamebuf, keyname, sizeof(keyname)); result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf); CHECK("dst_key_buildfilename", result); printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf), (char *)isc_buffer_base(&keynamebuf)); type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY; result = dst_key_tofile(tsigkey->key, type, ""); CHECK("dst_key_tofile", result); dns_message_destroy(&query); dns_message_destroy(&response); dns_request_destroy(&reqev->request); isc_event_free(&event); isc_app_shutdown(); return; }
static void io(dns_name_t *name, int id, int alg, int type, isc_mem_t *mctx) { dst_key_t *key = NULL; isc_result_t ret; ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; use(key, mctx); dns(key, mctx); dst_key_free(&key); }
int main(int argc, char **argv) { UNUSED(argc); UNUSED(argv); rsa = RSA_new(); e = BN_new(); pkey = EVP_PKEY_new(); if ((rsa == NULL) || (e == NULL) || (pkey == NULL) || !EVP_PKEY_set1_RSA(pkey, rsa)) { fprintf(stderr, "fatal error: basic OpenSSL failure\n"); exit(1); } /* e = 0x1000000000001 */ BN_set_bit(e, 0); BN_set_bit(e, 48); if (RSA_generate_key_ex(rsa, bits, e, NULL)) { BN_free(e); RSA_free(rsa); } else { fprintf(stderr, "fatal error: RSA_generate_key_ex() fails " "at file %s line %d\n", __FILE__, __LINE__); exit(1); } dns_result_register(); CHECK(isc_mem_create(0, 0, &mctx), "isc_mem_create()"); CHECK(isc_entropy_create(mctx, &ectx), "isc_entropy_create()"); CHECK(isc_entropy_usebestsource(ectx, &source, "../random.data", ISC_ENTROPY_KEYBOARDNO), "isc_entropy_usebestsource(\"../random.data\")"); CHECK(dst_lib_init2(mctx, ectx, NULL, 0), "dst_lib_init2()"); CHECK(isc_log_create(mctx, &log_, &logconfig), "isc_log_create()"); isc_log_setcontext(log_); dns_log_init(log_); dns_log_setcontext(log_); CHECK(isc_log_settag(logconfig, "bigkey"), "isc_log_settag()"); destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; CHECK(isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level, &destination, ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL), "isc_log_createchannel()"); CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL), "isc_log_usechannel()"); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_constinit(&buf, "example.", strlen("example.")); isc_buffer_add(&buf, strlen("example.")); CHECK(dns_name_fromtext(name, &buf, dns_rootname, 0, NULL), "dns_name_fromtext(\"example.\")"); CHECK(dst_key_buildinternal(name, DNS_KEYALG_RSASHA1, bits, DNS_KEYOWNER_ZONE, DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, pkey, mctx, &key), "dst_key_buildinternal(...)"); CHECK(dst_key_tofile(key, DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, NULL), "dst_key_tofile()"); isc_buffer_init(&buf, filename, sizeof(filename) - 1); isc_buffer_clear(&buf); CHECK(dst_key_buildfilename(key, 0, NULL, &buf), "dst_key_buildfilename()"); printf("%s\n", filename); dst_key_free(&key); isc_log_destroy(&log_); isc_log_setcontext(NULL); dns_log_setcontext(NULL); if (source != NULL) isc_entropy_destroysource(&source); isc_entropy_detach(&ectx); dst_lib_destroy(); dns_name_destroy(); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char **argv) { isc_result_t result; #ifdef USE_PKCS11 const char *engine = "pkcs11"; #else const char *engine = NULL; #endif char *filename = NULL, *dir = NULL; char newname[1024], oldname[1024]; char keystr[DST_KEY_FORMATSIZE]; char *endp; int ch; isc_entropy_t *ectx = NULL; dst_key_t *key = NULL; isc_uint32_t flags; isc_buffer_t buf; isc_boolean_t force = ISC_FALSE; isc_boolean_t remove = ISC_FALSE; isc_boolean_t id = ISC_FALSE; if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("Out of memory"); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) { switch (ch) { case 'E': engine = isc_commandline_argument; break; case 'f': force = ISC_TRUE; break; case 'K': /* * We don't have to copy it here, but do it to * simplify cleanup later */ dir = isc_mem_strdup(mctx, isc_commandline_argument); if (dir == NULL) { fatal("Failed to allocate memory for " "directory"); } break; case 'r': remove = ISC_TRUE; break; case 'R': id = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* Falls into */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (argc < isc_commandline_index + 1 || argv[isc_commandline_index] == NULL) fatal("The key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("Extraneous arguments"); if (dir != NULL) { filename = argv[isc_commandline_index]; } else { result = isc_file_splitpath(mctx, argv[isc_commandline_index], &dir, &filename); if (result != ISC_R_SUCCESS) fatal("cannot process filename %s: %s", argv[isc_commandline_index], isc_result_totext(result)); if (strcmp(dir, ".") == 0) { isc_mem_free(mctx, dir); dir = NULL; } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("Could not initialize hash"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("Could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); result = dst_key_fromnamedfile(filename, dir, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, mctx, &key); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (id) { fprintf(stdout, "%u\n", dst_key_rid(key)); goto cleanup; } dst_key_format(key, keystr, sizeof(keystr)); if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); if (force) set_keyversion(key); else check_keyversion(key, keystr); flags = dst_key_flags(key); if ((flags & DNS_KEYFLAG_REVOKE) == 0) { isc_stdtime_t now; if ((flags & DNS_KEYFLAG_KSK) == 0) fprintf(stderr, "%s: warning: Key is not flagged " "as a KSK. Revoking a ZSK is " "legal, but undefined.\n", program); isc_stdtime_get(&now); dst_key_settime(key, DST_TIME_REVOKE, now); dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE); isc_buffer_init(&buf, newname, sizeof(newname)); dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); if (access(newname, F_OK) == 0 && !force) { fatal("Key file %s already exists; " "use -f to force overwrite", newname); } result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, dir); if (result != ISC_R_SUCCESS) { dst_key_format(key, keystr, sizeof(keystr)); fatal("Failed to write key %s: %s", keystr, isc_result_totext(result)); } isc_buffer_clear(&buf); dst_key_buildfilename(key, 0, dir, &buf); printf("%s\n", newname); /* * Remove old key file, if told to (and if * it isn't the same as the new file) */ if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) { isc_buffer_init(&buf, oldname, sizeof(oldname)); dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE); dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); if (strcmp(oldname, newname) == 0) goto cleanup; (void)unlink(oldname); isc_buffer_clear(&buf); dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); (void)unlink(oldname); } } else { dst_key_format(key, keystr, sizeof(keystr)); fatal("Key %s is already revoked", keystr); } cleanup: dst_key_free(&key); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); if (verbose > 10) isc_mem_stats(mctx, stdout); if (dir != NULL) isc_mem_free(mctx, dir); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; dst_key_t *key = NULL, *oldkey; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, ksk = 0; dns_secalg_t alg; isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; isc_mem_t *mctx = NULL; int ch, rsa_exp = 0, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; if (argc == 1) usage(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "a:b:c:d:ef:g:kn:t:p:s:r:v:h")) != -1) { switch (ch) { case 'a': algname = isc_commandline_argument; break; case 'b': size = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || size < 0) fatal("-b requires a non-negative number"); break; case 'c': classname = isc_commandline_argument; break; case 'd': dbits = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || dbits < 0) fatal("-d requires a non-negative number"); break; case 'e': rsa_exp = 1; break; case 'f': if (strcasecmp(isc_commandline_argument, "KSK") == 0) ksk = DNS_KEYFLAG_KSK; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'g': generator = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || generator <= 0) fatal("-g requires a positive number"); break; case 'k': options |= DST_TYPE_KEY; break; case 'n': nametype = isc_commandline_argument; break; case 't': type = isc_commandline_argument; break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 's': signatory = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || signatory < 0 || signatory > 15) fatal("-s must be followed by a number " "[0..15]"); break; case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst"); setup_logging(verbose, mctx, &log); if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (algname == NULL) fatal("no algorithm was specified"); if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " "specify \"-a RSAMD5\"\n"); return (1); } else if (strcasecmp(algname, "HMAC-MD5") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACMD5; } else if (strcasecmp(algname, "HMAC-SHA1") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA1; } else if (strcasecmp(algname, "HMAC-SHA224") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA224; } else if (strcasecmp(algname, "HMAC-SHA256") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA256; } else if (strcasecmp(algname, "HMAC-SHA384") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA384; } else if (strcasecmp(algname, "HMAC-SHA512") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA512; } else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) { flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); if (size < 0) size = 0; } else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (size < 0) fatal("key size not specified (-b option)"); switch (alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: if (size != 0 && (size < 512 || size > MAX_RSA)) fatal("RSA key size %d out of range", size); break; case DNS_KEYALG_DH: if (size != 0 && (size < 128 || size > 4096)) fatal("DH key size %d out of range", size); break; case DNS_KEYALG_DSA: if (size != 0 && !dsa_size_ok(size)) fatal("invalid DSS key size: %d", size); break; case DST_ALG_HMACMD5: if (size < 1 || size > 512) fatal("HMAC-MD5 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 128)) fatal("HMAC-MD5 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-MD5 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA1: if (size < 1 || size > 160) fatal("HMAC-SHA1 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 160)) fatal("HMAC-SHA1 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA1 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA224: if (size < 1 || size > 224) fatal("HMAC-SHA224 key size %d out of range", size); if (dbits != 0 && (dbits < 112 || dbits > 224)) fatal("HMAC-SHA224 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA224 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA256: if (size < 1 || size > 256) fatal("HMAC-SHA256 key size %d out of range", size); if (dbits != 0 && (dbits < 128 || dbits > 256)) fatal("HMAC-SHA256 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA256 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA384: if (size < 1 || size > 384) fatal("HMAC-384 key size %d out of range", size); if (dbits != 0 && (dbits < 192 || dbits > 384)) fatal("HMAC-SHA384 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA384 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA512: if (size < 1 || size > 512) fatal("HMAC-SHA512 key size %d out of range", size); if (dbits != 0 && (dbits < 256 || dbits > 512)) fatal("HMAC-SHA512 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA512 digest bits %d not divisible by 8", dbits); break; } if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1) && rsa_exp != 0) fatal("specified RSA exponent for a non-RSA key"); if (alg != DNS_KEYALG_DH && generator != 0) fatal("specified DH generator for a non-DH key"); if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY / HMAC */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ flags |= ksk; if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if (size > 0) fatal("specified null key with non-zero size"); if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)) fatal("a key with algorithm '%s' cannot be a zone key", algname); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); switch(alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: param = rsa_exp; break; case DNS_KEYALG_DH: param = generator; break; case DNS_KEYALG_DSA: case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: case DST_ALG_HMACSHA384: case DST_ALG_HMACSHA512: param = 0; break; } if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) null_key = ISC_TRUE; isc_buffer_init(&buf, filename, sizeof(filename) - 1); do { conflict = ISC_FALSE; oldkey = NULL; /* generate the key */ ret = dst_key_generate(name, alg, size, param, flags, protocol, rdclass, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[ALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); alg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); exit(-1); } dst_key_setbits(key, dbits); /* * Try to read a key with the same name, alg and id from disk. * If there is one we must continue generating a new one * unless we were asked to generate a null key, in which * case we return failure. */ ret = dst_key_fromfile(name, dst_key_id(key), alg, DST_TYPE_PRIVATE, NULL, mctx, &oldkey); /* do not overwrite an existing key */ if (ret == ISC_R_SUCCESS) { dst_key_free(&oldkey); conflict = ISC_TRUE; if (null_key) break; } if (conflict == ISC_TRUE) { if (verbose > 0) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); fprintf(stderr, "%s: %s already exists, " "generating a new key\n", program, filename); } dst_key_free(&key); } } while (conflict == ISC_TRUE); if (conflict) fatal("cannot generate a null key when a key with id 0 " "already exists"); ret = dst_key_tofile(key, options, NULL); if (ret != ISC_R_SUCCESS) { char keystr[KEY_FORMATSIZE]; key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char **argv) { isc_result_t result; #ifdef USE_PKCS11 const char *engine = "pkcs11"; #else const char *engine = NULL; #endif char *filename = NULL, *directory = NULL; char newname[1024]; char keystr[DST_KEY_FORMATSIZE]; char *endp, *p; int ch; isc_entropy_t *ectx = NULL; const char *predecessor = NULL; dst_key_t *prevkey = NULL; dst_key_t *key = NULL; isc_buffer_t buf; dns_name_t *name = NULL; dns_secalg_t alg = 0; unsigned int size = 0; isc_uint16_t flags = 0; int prepub = -1; dns_ttl_t ttl = 0; isc_stdtime_t now; isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; isc_boolean_t printcreate = ISC_FALSE, printpub = ISC_FALSE; isc_boolean_t printact = ISC_FALSE, printrev = ISC_FALSE; isc_boolean_t printinact = ISC_FALSE, printdel = ISC_FALSE; isc_boolean_t force = ISC_FALSE; isc_boolean_t epoch = ISC_FALSE; isc_boolean_t changed = ISC_FALSE; isc_log_t *log = NULL; isc__mem_register(); if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("Out of memory"); setup_logging(verbose, mctx, &log); dns_result_register(); isc_commandline_errprint = ISC_FALSE; isc_stdtime_get(&now); #define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'E': engine = isc_commandline_argument; break; case 'f': force = ISC_TRUE; break; case 'p': p = isc_commandline_argument; if (!strcasecmp(p, "all")) { printcreate = ISC_TRUE; printpub = ISC_TRUE; printact = ISC_TRUE; printrev = ISC_TRUE; printinact = ISC_TRUE; printdel = ISC_TRUE; break; } do { switch (*p++) { case 'C': printcreate = ISC_TRUE; break; case 'P': printpub = ISC_TRUE; break; case 'A': printact = ISC_TRUE; break; case 'R': printrev = ISC_TRUE; break; case 'I': printinact = ISC_TRUE; break; case 'D': printdel = ISC_TRUE; break; case ' ': break; default: usage(); break; } } while (*p != '\0'); break; case 'u': epoch = ISC_TRUE; break; case 'K': /* * We don't have to copy it here, but do it to * simplify cleanup later */ directory = isc_mem_strdup(mctx, isc_commandline_argument); if (directory == NULL) { fatal("Failed to allocate memory for " "directory"); } break; case 'L': if (strcmp(isc_commandline_argument, "none") == 0) ttl = 0; else ttl = strtottl(isc_commandline_argument); setttl = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'P': if (setpub || unsetpub) fatal("-P specified more than once"); changed = ISC_TRUE; if (!strcasecmp(isc_commandline_argument, "none")) { unsetpub = ISC_TRUE; } else { setpub = ISC_TRUE; pub = strtotime(isc_commandline_argument, now, now); } break; case 'A': if (setact || unsetact) fatal("-A specified more than once"); changed = ISC_TRUE; if (!strcasecmp(isc_commandline_argument, "none")) { unsetact = ISC_TRUE; } else { setact = ISC_TRUE; act = strtotime(isc_commandline_argument, now, now); } break; case 'R': if (setrev || unsetrev) fatal("-R specified more than once"); changed = ISC_TRUE; if (!strcasecmp(isc_commandline_argument, "none")) { unsetrev = ISC_TRUE; } else { setrev = ISC_TRUE; rev = strtotime(isc_commandline_argument, now, now); } break; case 'I': if (setinact || unsetinact) fatal("-I specified more than once"); changed = ISC_TRUE; if (!strcasecmp(isc_commandline_argument, "none")) { unsetinact = ISC_TRUE; } else { setinact = ISC_TRUE; inact = strtotime(isc_commandline_argument, now, now); } break; case 'D': if (setdel || unsetdel) fatal("-D specified more than once"); changed = ISC_TRUE; if (!strcasecmp(isc_commandline_argument, "none")) { unsetdel = ISC_TRUE; } else { setdel = ISC_TRUE; del = strtotime(isc_commandline_argument, now, now); } break; case 'S': predecessor = isc_commandline_argument; break; case 'i': prepub = strtottl(isc_commandline_argument); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* Falls into */ case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (argc < isc_commandline_index + 1 || argv[isc_commandline_index] == NULL) fatal("The key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("Extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("Could not initialize hash"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("Could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); if (predecessor != NULL) { char keystr[DST_KEY_FORMATSIZE]; isc_stdtime_t when; int major, minor; if (prepub == -1) prepub = (30 * 86400); if (setpub || unsetpub) fatal("-S and -P cannot be used together"); if (setact || unsetact) fatal("-S and -A cannot be used together"); result = dst_key_fromnamedfile(predecessor, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &prevkey); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", filename, isc_result_totext(result)); if (!dst_key_isprivate(prevkey)) fatal("%s is not a private key", filename); name = dst_key_name(prevkey); alg = dst_key_alg(prevkey); size = dst_key_size(prevkey); flags = dst_key_flags(prevkey); dst_key_format(prevkey, keystr, sizeof(keystr)); dst_key_getprivateformat(prevkey, &major, &minor); if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) fatal("Predecessor has incompatible format " "version %d.%d\n\t", major, minor); result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); if (result != ISC_R_SUCCESS) fatal("Predecessor has no activation date. " "You must set one before\n\t" "generating a successor."); result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &act); if (result != ISC_R_SUCCESS) fatal("Predecessor has no inactivation date. " "You must set one before\n\t" "generating a successor."); pub = act - prepub; if (pub < now && prepub != 0) fatal("Predecessor will become inactive before the\n\t" "prepublication period ends. Either change " "its inactivation date,\n\t" "or use the -i option to set a shorter " "prepublication interval."); result = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); if (result != ISC_R_SUCCESS) fprintf(stderr, "%s: WARNING: Predecessor has no " "removal date;\n\t" "it will remain in the zone " "indefinitely after rollover.\n", program); changed = setpub = setact = ISC_TRUE; dst_key_free(&prevkey); } else { if (prepub < 0) prepub = 0; if (prepub > 0) { if (setpub && setact && (act - prepub) < pub) fatal("Activation and publication dates " "are closer together than the\n\t" "prepublication interval."); if (setpub && !setact) { setact = ISC_TRUE; act = pub + prepub; } else if (setact && !setpub) { setpub = ISC_TRUE; pub = act - prepub; } if ((act - prepub) < now) fatal("Time until activation is shorter " "than the\n\tprepublication interval."); } } if (directory != NULL) { filename = argv[isc_commandline_index]; } else { result = isc_file_splitpath(mctx, argv[isc_commandline_index], &directory, &filename); if (result != ISC_R_SUCCESS) fatal("cannot process filename %s: %s", argv[isc_commandline_index], isc_result_totext(result)); } result = dst_key_fromnamedfile(filename, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &key); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", filename, isc_result_totext(result)); if (!dst_key_isprivate(key)) fatal("%s is not a private key", filename); dst_key_format(key, keystr, sizeof(keystr)); if (predecessor != NULL) { if (!dns_name_equal(name, dst_key_name(key))) fatal("Key name mismatch"); if (alg != dst_key_alg(key)) fatal("Key algorithm mismatch"); if (size != dst_key_size(key)) fatal("Key size mismatch"); if (flags != dst_key_flags(key)) fatal("Key flags mismatch"); } if (force) set_keyversion(key); else check_keyversion(key, keystr); if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); /* * Set time values. */ if (setpub) dst_key_settime(key, DST_TIME_PUBLISH, pub); else if (unsetpub) dst_key_unsettime(key, DST_TIME_PUBLISH); if (setact) dst_key_settime(key, DST_TIME_ACTIVATE, act); else if (unsetact) dst_key_unsettime(key, DST_TIME_ACTIVATE); if (setrev) { if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) fprintf(stderr, "%s: warning: Key %s is already " "revoked; changing the revocation date " "will not affect this.\n", program, keystr); if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) fprintf(stderr, "%s: warning: Key %s is not flagged as " "a KSK, but -R was used. Revoking a " "ZSK is legal, but undefined.\n", program, keystr); dst_key_settime(key, DST_TIME_REVOKE, rev); } else if (unsetrev) { if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) fprintf(stderr, "%s: warning: Key %s is already " "revoked; removing the revocation date " "will not affect this.\n", program, keystr); dst_key_unsettime(key, DST_TIME_REVOKE); } if (setinact) dst_key_settime(key, DST_TIME_INACTIVE, inact); else if (unsetinact) dst_key_unsettime(key, DST_TIME_INACTIVE); if (setdel) dst_key_settime(key, DST_TIME_DELETE, del); else if (unsetdel) dst_key_unsettime(key, DST_TIME_DELETE); if (setttl) dst_key_setttl(key, ttl); /* * No metadata changes were made but we're forcing an upgrade * to the new format anyway: use "-P now -A now" as the default */ if (force && !changed) { dst_key_settime(key, DST_TIME_PUBLISH, now); dst_key_settime(key, DST_TIME_ACTIVATE, now); changed = ISC_TRUE; } if (!changed && setttl) changed = ISC_TRUE; /* * Print out time values, if -p was used. */ if (printcreate) printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); if (printpub) printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); if (printact) printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); if (printrev) printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); if (printinact) printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); if (printdel) printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); if (changed) { isc_buffer_init(&buf, newname, sizeof(newname)); result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build public key filename: %s", isc_result_totext(result)); } result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, directory); if (result != ISC_R_SUCCESS) { dst_key_format(key, keystr, sizeof(keystr)); fatal("Failed to write key %s: %s", keystr, isc_result_totext(result)); } printf("%s\n", newname); isc_buffer_clear(&buf); result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build private key filename: %s", isc_result_totext(result)); } printf("%s\n", newname); } dst_key_free(&key); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); if (verbose > 10) isc_mem_stats(mctx, stdout); cleanup_logging(&log); isc_mem_free(mctx, directory); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; dst_key_t *key = NULL, *oldkey; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, ksk = 0; dns_secalg_t alg; isc_boolean_t null_key = ISC_FALSE; isc_mem_t *mctx = NULL; int ch; int protocol = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; char *label = NULL; if (argc == 1) usage(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "a:c:f:kl:n:p:t:v:h")) != -1) { switch (ch) { case 'a': algname = isc_commandline_argument; break; case 'c': classname = isc_commandline_argument; break; case 'f': if (strcasecmp(isc_commandline_argument, "KSK") == 0) ksk = DNS_KEYFLAG_KSK; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'k': options |= DST_TYPE_KEY; break; case 'l': label = isc_commandline_argument; break; case 'n': nametype = isc_commandline_argument; break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 't': type = isc_commandline_argument; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst"); setup_logging(verbose, mctx, &log); if (label == NULL) fatal("the key label was not specified"); if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (algname == NULL) fatal("no algorithm was specified"); if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " "specify \"-a RSAMD5\"\n"); return (1); } else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) { flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); } else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if ((options & DST_TYPE_KEY) != 0) /* KEY */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ flags |= ksk; if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && alg == DNS_KEYALG_DH) fatal("a key with algorithm '%s' cannot be a zone key", algname); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) null_key = ISC_TRUE; isc_buffer_init(&buf, filename, sizeof(filename) - 1); /* associate the key */ ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, "", label, NULL, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[ALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); alg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); exit(-1); } /* * Try to read a key with the same name, alg and id from disk. * If there is one we must continue generating a new one * unless we were asked to generate a null key, in which * case we return failure. */ ret = dst_key_fromfile(name, dst_key_id(key), alg, DST_TYPE_PRIVATE, NULL, mctx, &oldkey); /* do not overwrite an existing key */ if (ret == ISC_R_SUCCESS) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); fprintf(stderr, "%s: %s already exists\n", program, filename); dst_key_free(&key); exit (1); } ret = dst_key_tofile(key, options, NULL); if (ret != ISC_R_SUCCESS) { char keystr[KEY_FORMATSIZE]; key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }