/contrib/bind9/lib/dns/dst_api.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1777 lines · 1495 code · 203 blank · 79 comment · 320 complexity · 887f96fca8132c4b81a30f6b53904cc7 MD5 · raw file

  1. /*
  2. * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Portions Copyright (C) 1999-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  10. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
  12. * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  15. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. *
  17. * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
  18. *
  19. * Permission to use, copy, modify, and/or distribute this software for any
  20. * purpose with or without fee is hereby granted, provided that the above
  21. * copyright notice and this permission notice appear in all copies.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  24. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
  26. * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  27. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  28. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  29. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30. */
  31. /*
  32. * Principal Author: Brian Wellington
  33. * $Id$
  34. */
  35. /*! \file */
  36. #include <config.h>
  37. #include <stdlib.h>
  38. #include <time.h>
  39. #include <isc/buffer.h>
  40. #include <isc/dir.h>
  41. #include <isc/entropy.h>
  42. #include <isc/fsaccess.h>
  43. #include <isc/hmacsha.h>
  44. #include <isc/lex.h>
  45. #include <isc/mem.h>
  46. #include <isc/once.h>
  47. #include <isc/platform.h>
  48. #include <isc/print.h>
  49. #include <isc/refcount.h>
  50. #include <isc/random.h>
  51. #include <isc/string.h>
  52. #include <isc/time.h>
  53. #include <isc/util.h>
  54. #include <dns/fixedname.h>
  55. #include <dns/keyvalues.h>
  56. #include <dns/name.h>
  57. #include <dns/rdata.h>
  58. #include <dns/rdataclass.h>
  59. #include <dns/ttl.h>
  60. #include <dns/types.h>
  61. #include <dst/result.h>
  62. #include "dst_internal.h"
  63. #define DST_AS_STR(t) ((t).value.as_textregion.base)
  64. static dst_func_t *dst_t_func[DST_MAX_ALGS];
  65. #ifdef BIND9
  66. static isc_entropy_t *dst_entropy_pool = NULL;
  67. #endif
  68. static unsigned int dst_entropy_flags = 0;
  69. static isc_boolean_t dst_initialized = ISC_FALSE;
  70. void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
  71. isc_mem_t *dst__memory_pool = NULL;
  72. /*
  73. * Static functions.
  74. */
  75. static dst_key_t * get_key_struct(dns_name_t *name,
  76. unsigned int alg,
  77. unsigned int flags,
  78. unsigned int protocol,
  79. unsigned int bits,
  80. dns_rdataclass_t rdclass,
  81. isc_mem_t *mctx);
  82. static isc_result_t write_public_key(const dst_key_t *key, int type,
  83. const char *directory);
  84. static isc_result_t buildfilename(dns_name_t *name,
  85. dns_keytag_t id,
  86. unsigned int alg,
  87. unsigned int type,
  88. const char *directory,
  89. isc_buffer_t *out);
  90. static isc_result_t computeid(dst_key_t *key);
  91. static isc_result_t frombuffer(dns_name_t *name,
  92. unsigned int alg,
  93. unsigned int flags,
  94. unsigned int protocol,
  95. dns_rdataclass_t rdclass,
  96. isc_buffer_t *source,
  97. isc_mem_t *mctx,
  98. dst_key_t **keyp);
  99. static isc_result_t algorithm_status(unsigned int alg);
  100. static isc_result_t addsuffix(char *filename, int len,
  101. const char *dirname, const char *ofilename,
  102. const char *suffix);
  103. #define RETERR(x) \
  104. do { \
  105. result = (x); \
  106. if (result != ISC_R_SUCCESS) \
  107. goto out; \
  108. } while (0)
  109. #define CHECKALG(alg) \
  110. do { \
  111. isc_result_t _r; \
  112. _r = algorithm_status(alg); \
  113. if (_r != ISC_R_SUCCESS) \
  114. return (_r); \
  115. } while (0); \
  116. #if defined(OPENSSL) && defined(BIND9)
  117. static void *
  118. default_memalloc(void *arg, size_t size) {
  119. UNUSED(arg);
  120. if (size == 0U)
  121. size = 1;
  122. return (malloc(size));
  123. }
  124. static void
  125. default_memfree(void *arg, void *ptr) {
  126. UNUSED(arg);
  127. free(ptr);
  128. }
  129. #endif
  130. isc_result_t
  131. dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
  132. return (dst_lib_init2(mctx, ectx, NULL, eflags));
  133. }
  134. isc_result_t
  135. dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
  136. const char *engine, unsigned int eflags) {
  137. isc_result_t result;
  138. REQUIRE(mctx != NULL);
  139. #ifdef BIND9
  140. REQUIRE(ectx != NULL);
  141. #else
  142. UNUSED(ectx);
  143. #endif
  144. REQUIRE(dst_initialized == ISC_FALSE);
  145. #ifndef OPENSSL
  146. UNUSED(engine);
  147. #endif
  148. dst__memory_pool = NULL;
  149. #if defined(OPENSSL) && defined(BIND9)
  150. UNUSED(mctx);
  151. /*
  152. * When using --with-openssl, there seems to be no good way of not
  153. * leaking memory due to the openssl error handling mechanism.
  154. * Avoid assertions by using a local memory context and not checking
  155. * for leaks on exit. Note: as there are leaks we cannot use
  156. * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
  157. * by libcrypto.
  158. */
  159. result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
  160. NULL, &dst__memory_pool, 0);
  161. if (result != ISC_R_SUCCESS)
  162. return (result);
  163. isc_mem_setname(dst__memory_pool, "dst", NULL);
  164. #ifndef OPENSSL_LEAKS
  165. isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
  166. #endif
  167. #else
  168. isc_mem_attach(mctx, &dst__memory_pool);
  169. #endif
  170. #ifdef BIND9
  171. isc_entropy_attach(ectx, &dst_entropy_pool);
  172. #endif
  173. dst_entropy_flags = eflags;
  174. dst_result_register();
  175. memset(dst_t_func, 0, sizeof(dst_t_func));
  176. RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
  177. RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
  178. RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
  179. RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
  180. RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
  181. RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
  182. #ifdef OPENSSL
  183. RETERR(dst__openssl_init(engine));
  184. RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5],
  185. DST_ALG_RSAMD5));
  186. RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
  187. DST_ALG_RSASHA1));
  188. RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
  189. DST_ALG_NSEC3RSASHA1));
  190. RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
  191. DST_ALG_RSASHA256));
  192. RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
  193. DST_ALG_RSASHA512));
  194. #ifdef HAVE_OPENSSL_DSA
  195. RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
  196. RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
  197. #endif
  198. RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
  199. #ifdef HAVE_OPENSSL_GOST
  200. RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST]));
  201. #endif
  202. #endif /* OPENSSL */
  203. #ifdef GSSAPI
  204. RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
  205. #endif
  206. dst_initialized = ISC_TRUE;
  207. return (ISC_R_SUCCESS);
  208. out:
  209. /* avoid immediate crash! */
  210. dst_initialized = ISC_TRUE;
  211. dst_lib_destroy();
  212. return (result);
  213. }
  214. void
  215. dst_lib_destroy(void) {
  216. int i;
  217. RUNTIME_CHECK(dst_initialized == ISC_TRUE);
  218. dst_initialized = ISC_FALSE;
  219. for (i = 0; i < DST_MAX_ALGS; i++)
  220. if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL)
  221. dst_t_func[i]->cleanup();
  222. #ifdef OPENSSL
  223. dst__openssl_destroy();
  224. #endif
  225. if (dst__memory_pool != NULL)
  226. isc_mem_detach(&dst__memory_pool);
  227. #ifdef BIND9
  228. if (dst_entropy_pool != NULL)
  229. isc_entropy_detach(&dst_entropy_pool);
  230. #endif
  231. }
  232. isc_boolean_t
  233. dst_algorithm_supported(unsigned int alg) {
  234. REQUIRE(dst_initialized == ISC_TRUE);
  235. if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
  236. return (ISC_FALSE);
  237. return (ISC_TRUE);
  238. }
  239. isc_result_t
  240. dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
  241. dst_context_t *dctx;
  242. isc_result_t result;
  243. REQUIRE(dst_initialized == ISC_TRUE);
  244. REQUIRE(VALID_KEY(key));
  245. REQUIRE(mctx != NULL);
  246. REQUIRE(dctxp != NULL && *dctxp == NULL);
  247. if (key->func->createctx == NULL)
  248. return (DST_R_UNSUPPORTEDALG);
  249. if (key->keydata.generic == NULL)
  250. return (DST_R_NULLKEY);
  251. dctx = isc_mem_get(mctx, sizeof(dst_context_t));
  252. if (dctx == NULL)
  253. return (ISC_R_NOMEMORY);
  254. dctx->key = key;
  255. dctx->mctx = mctx;
  256. result = key->func->createctx(key, dctx);
  257. if (result != ISC_R_SUCCESS) {
  258. isc_mem_put(mctx, dctx, sizeof(dst_context_t));
  259. return (result);
  260. }
  261. dctx->magic = CTX_MAGIC;
  262. *dctxp = dctx;
  263. return (ISC_R_SUCCESS);
  264. }
  265. void
  266. dst_context_destroy(dst_context_t **dctxp) {
  267. dst_context_t *dctx;
  268. REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
  269. dctx = *dctxp;
  270. INSIST(dctx->key->func->destroyctx != NULL);
  271. dctx->key->func->destroyctx(dctx);
  272. dctx->magic = 0;
  273. isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t));
  274. *dctxp = NULL;
  275. }
  276. isc_result_t
  277. dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
  278. REQUIRE(VALID_CTX(dctx));
  279. REQUIRE(data != NULL);
  280. INSIST(dctx->key->func->adddata != NULL);
  281. return (dctx->key->func->adddata(dctx, data));
  282. }
  283. isc_result_t
  284. dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  285. dst_key_t *key;
  286. REQUIRE(VALID_CTX(dctx));
  287. REQUIRE(sig != NULL);
  288. key = dctx->key;
  289. CHECKALG(key->key_alg);
  290. if (key->keydata.generic == NULL)
  291. return (DST_R_NULLKEY);
  292. if (key->func->sign == NULL)
  293. return (DST_R_NOTPRIVATEKEY);
  294. if (key->func->isprivate == NULL ||
  295. key->func->isprivate(key) == ISC_FALSE)
  296. return (DST_R_NOTPRIVATEKEY);
  297. return (key->func->sign(dctx, sig));
  298. }
  299. isc_result_t
  300. dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
  301. REQUIRE(VALID_CTX(dctx));
  302. REQUIRE(sig != NULL);
  303. CHECKALG(dctx->key->key_alg);
  304. if (dctx->key->keydata.generic == NULL)
  305. return (DST_R_NULLKEY);
  306. if (dctx->key->func->verify == NULL)
  307. return (DST_R_NOTPUBLICKEY);
  308. return (dctx->key->func->verify(dctx, sig));
  309. }
  310. isc_result_t
  311. dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
  312. isc_buffer_t *secret)
  313. {
  314. REQUIRE(dst_initialized == ISC_TRUE);
  315. REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
  316. REQUIRE(secret != NULL);
  317. CHECKALG(pub->key_alg);
  318. CHECKALG(priv->key_alg);
  319. if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
  320. return (DST_R_NULLKEY);
  321. if (pub->key_alg != priv->key_alg ||
  322. pub->func->computesecret == NULL ||
  323. priv->func->computesecret == NULL)
  324. return (DST_R_KEYCANNOTCOMPUTESECRET);
  325. if (dst_key_isprivate(priv) == ISC_FALSE)
  326. return (DST_R_NOTPRIVATEKEY);
  327. return (pub->func->computesecret(pub, priv, secret));
  328. }
  329. isc_result_t
  330. dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
  331. isc_result_t ret = ISC_R_SUCCESS;
  332. REQUIRE(dst_initialized == ISC_TRUE);
  333. REQUIRE(VALID_KEY(key));
  334. REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
  335. CHECKALG(key->key_alg);
  336. if (key->func->tofile == NULL)
  337. return (DST_R_UNSUPPORTEDALG);
  338. if (type & DST_TYPE_PUBLIC) {
  339. ret = write_public_key(key, type, directory);
  340. if (ret != ISC_R_SUCCESS)
  341. return (ret);
  342. }
  343. if ((type & DST_TYPE_PRIVATE) &&
  344. (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
  345. return (key->func->tofile(key, directory));
  346. else
  347. return (ISC_R_SUCCESS);
  348. }
  349. isc_result_t
  350. dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
  351. unsigned int alg, int type, const char *directory,
  352. isc_mem_t *mctx, dst_key_t **keyp)
  353. {
  354. char filename[ISC_DIR_NAMEMAX];
  355. isc_buffer_t b;
  356. dst_key_t *key;
  357. isc_result_t result;
  358. REQUIRE(dst_initialized == ISC_TRUE);
  359. REQUIRE(dns_name_isabsolute(name));
  360. REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
  361. REQUIRE(mctx != NULL);
  362. REQUIRE(keyp != NULL && *keyp == NULL);
  363. CHECKALG(alg);
  364. isc_buffer_init(&b, filename, sizeof(filename));
  365. result = buildfilename(name, id, alg, type, directory, &b);
  366. if (result != ISC_R_SUCCESS)
  367. return (result);
  368. key = NULL;
  369. result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key);
  370. if (result != ISC_R_SUCCESS)
  371. return (result);
  372. result = computeid(key);
  373. if (result != ISC_R_SUCCESS) {
  374. dst_key_free(&key);
  375. return (result);
  376. }
  377. if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
  378. alg != key->key_alg) {
  379. dst_key_free(&key);
  380. return (DST_R_INVALIDPRIVATEKEY);
  381. }
  382. *keyp = key;
  383. return (ISC_R_SUCCESS);
  384. }
  385. isc_result_t
  386. dst_key_fromnamedfile(const char *filename, const char *dirname,
  387. int type, isc_mem_t *mctx, dst_key_t **keyp)
  388. {
  389. isc_result_t result;
  390. dst_key_t *pubkey = NULL, *key = NULL;
  391. char *newfilename = NULL;
  392. int newfilenamelen = 0;
  393. isc_lex_t *lex = NULL;
  394. REQUIRE(dst_initialized == ISC_TRUE);
  395. REQUIRE(filename != NULL);
  396. REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
  397. REQUIRE(mctx != NULL);
  398. REQUIRE(keyp != NULL && *keyp == NULL);
  399. /* If an absolute path is specified, don't use the key directory */
  400. #ifndef WIN32
  401. if (filename[0] == '/')
  402. dirname = NULL;
  403. #else /* WIN32 */
  404. if (filename[0] == '/' || filename[0] == '\\')
  405. dirname = NULL;
  406. #endif
  407. newfilenamelen = strlen(filename) + 5;
  408. if (dirname != NULL)
  409. newfilenamelen += strlen(dirname) + 1;
  410. newfilename = isc_mem_get(mctx, newfilenamelen);
  411. if (newfilename == NULL)
  412. return (ISC_R_NOMEMORY);
  413. result = addsuffix(newfilename, newfilenamelen,
  414. dirname, filename, ".key");
  415. INSIST(result == ISC_R_SUCCESS);
  416. result = dst_key_read_public(newfilename, type, mctx, &pubkey);
  417. isc_mem_put(mctx, newfilename, newfilenamelen);
  418. newfilename = NULL;
  419. if (result != ISC_R_SUCCESS)
  420. return (result);
  421. if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
  422. (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
  423. result = computeid(pubkey);
  424. if (result != ISC_R_SUCCESS) {
  425. dst_key_free(&pubkey);
  426. return (result);
  427. }
  428. *keyp = pubkey;
  429. return (ISC_R_SUCCESS);
  430. }
  431. result = algorithm_status(pubkey->key_alg);
  432. if (result != ISC_R_SUCCESS) {
  433. dst_key_free(&pubkey);
  434. return (result);
  435. }
  436. key = get_key_struct(pubkey->key_name, pubkey->key_alg,
  437. pubkey->key_flags, pubkey->key_proto, 0,
  438. pubkey->key_class, mctx);
  439. if (key == NULL) {
  440. dst_key_free(&pubkey);
  441. return (ISC_R_NOMEMORY);
  442. }
  443. if (key->func->parse == NULL)
  444. RETERR(DST_R_UNSUPPORTEDALG);
  445. newfilenamelen = strlen(filename) + 9;
  446. if (dirname != NULL)
  447. newfilenamelen += strlen(dirname) + 1;
  448. newfilename = isc_mem_get(mctx, newfilenamelen);
  449. if (newfilename == NULL)
  450. RETERR(ISC_R_NOMEMORY);
  451. result = addsuffix(newfilename, newfilenamelen,
  452. dirname, filename, ".private");
  453. INSIST(result == ISC_R_SUCCESS);
  454. RETERR(isc_lex_create(mctx, 1500, &lex));
  455. RETERR(isc_lex_openfile(lex, newfilename));
  456. isc_mem_put(mctx, newfilename, newfilenamelen);
  457. RETERR(key->func->parse(key, lex, pubkey));
  458. isc_lex_destroy(&lex);
  459. RETERR(computeid(key));
  460. if (pubkey->key_id != key->key_id)
  461. RETERR(DST_R_INVALIDPRIVATEKEY);
  462. dst_key_free(&pubkey);
  463. *keyp = key;
  464. return (ISC_R_SUCCESS);
  465. out:
  466. if (pubkey != NULL)
  467. dst_key_free(&pubkey);
  468. if (newfilename != NULL)
  469. isc_mem_put(mctx, newfilename, newfilenamelen);
  470. if (lex != NULL)
  471. isc_lex_destroy(&lex);
  472. dst_key_free(&key);
  473. return (result);
  474. }
  475. isc_result_t
  476. dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
  477. REQUIRE(dst_initialized == ISC_TRUE);
  478. REQUIRE(VALID_KEY(key));
  479. REQUIRE(target != NULL);
  480. CHECKALG(key->key_alg);
  481. if (key->func->todns == NULL)
  482. return (DST_R_UNSUPPORTEDALG);
  483. if (isc_buffer_availablelength(target) < 4)
  484. return (ISC_R_NOSPACE);
  485. isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
  486. isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
  487. isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
  488. if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
  489. if (isc_buffer_availablelength(target) < 2)
  490. return (ISC_R_NOSPACE);
  491. isc_buffer_putuint16(target,
  492. (isc_uint16_t)((key->key_flags >> 16)
  493. & 0xffff));
  494. }
  495. if (key->keydata.generic == NULL) /*%< NULL KEY */
  496. return (ISC_R_SUCCESS);
  497. return (key->func->todns(key, target));
  498. }
  499. isc_result_t
  500. dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
  501. isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
  502. {
  503. isc_uint8_t alg, proto;
  504. isc_uint32_t flags, extflags;
  505. dst_key_t *key = NULL;
  506. dns_keytag_t id, rid;
  507. isc_region_t r;
  508. isc_result_t result;
  509. REQUIRE(dst_initialized);
  510. isc_buffer_remainingregion(source, &r);
  511. if (isc_buffer_remaininglength(source) < 4)
  512. return (DST_R_INVALIDPUBLICKEY);
  513. flags = isc_buffer_getuint16(source);
  514. proto = isc_buffer_getuint8(source);
  515. alg = isc_buffer_getuint8(source);
  516. id = dst_region_computeid(&r, alg);
  517. rid = dst_region_computerid(&r, alg);
  518. if (flags & DNS_KEYFLAG_EXTENDED) {
  519. if (isc_buffer_remaininglength(source) < 2)
  520. return (DST_R_INVALIDPUBLICKEY);
  521. extflags = isc_buffer_getuint16(source);
  522. flags |= (extflags << 16);
  523. }
  524. result = frombuffer(name, alg, flags, proto, rdclass, source,
  525. mctx, &key);
  526. if (result != ISC_R_SUCCESS)
  527. return (result);
  528. key->key_id = id;
  529. key->key_rid = rid;
  530. *keyp = key;
  531. return (ISC_R_SUCCESS);
  532. }
  533. isc_result_t
  534. dst_key_frombuffer(dns_name_t *name, unsigned int alg,
  535. unsigned int flags, unsigned int protocol,
  536. dns_rdataclass_t rdclass,
  537. isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
  538. {
  539. dst_key_t *key = NULL;
  540. isc_result_t result;
  541. REQUIRE(dst_initialized);
  542. result = frombuffer(name, alg, flags, protocol, rdclass, source,
  543. mctx, &key);
  544. if (result != ISC_R_SUCCESS)
  545. return (result);
  546. result = computeid(key);
  547. if (result != ISC_R_SUCCESS) {
  548. dst_key_free(&key);
  549. return (result);
  550. }
  551. *keyp = key;
  552. return (ISC_R_SUCCESS);
  553. }
  554. isc_result_t
  555. dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
  556. REQUIRE(dst_initialized == ISC_TRUE);
  557. REQUIRE(VALID_KEY(key));
  558. REQUIRE(target != NULL);
  559. CHECKALG(key->key_alg);
  560. if (key->func->todns == NULL)
  561. return (DST_R_UNSUPPORTEDALG);
  562. return (key->func->todns(key, target));
  563. }
  564. isc_result_t
  565. dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
  566. isc_lex_t *lex = NULL;
  567. isc_result_t result = ISC_R_SUCCESS;
  568. REQUIRE(dst_initialized == ISC_TRUE);
  569. REQUIRE(VALID_KEY(key));
  570. REQUIRE(!dst_key_isprivate(key));
  571. REQUIRE(buffer != NULL);
  572. if (key->func->parse == NULL)
  573. RETERR(DST_R_UNSUPPORTEDALG);
  574. RETERR(isc_lex_create(key->mctx, 1500, &lex));
  575. RETERR(isc_lex_openbuffer(lex, buffer));
  576. RETERR(key->func->parse(key, lex, NULL));
  577. out:
  578. if (lex != NULL)
  579. isc_lex_destroy(&lex);
  580. return (result);
  581. }
  582. gss_ctx_id_t
  583. dst_key_getgssctx(const dst_key_t *key)
  584. {
  585. REQUIRE(key != NULL);
  586. return (key->keydata.gssctx);
  587. }
  588. isc_result_t
  589. dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
  590. dst_key_t **keyp, isc_region_t *intoken)
  591. {
  592. dst_key_t *key;
  593. isc_result_t result;
  594. REQUIRE(gssctx != NULL);
  595. REQUIRE(keyp != NULL && *keyp == NULL);
  596. key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
  597. 0, dns_rdataclass_in, mctx);
  598. if (key == NULL)
  599. return (ISC_R_NOMEMORY);
  600. if (intoken != NULL) {
  601. /*
  602. * Keep the token for use by external ssu rules. They may need
  603. * to examine the PAC in the kerberos ticket.
  604. */
  605. RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
  606. intoken->length));
  607. RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
  608. }
  609. key->keydata.gssctx = gssctx;
  610. *keyp = key;
  611. result = ISC_R_SUCCESS;
  612. out:
  613. return result;
  614. }
  615. isc_result_t
  616. dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
  617. unsigned int protocol, dns_rdataclass_t rdclass,
  618. const char *engine, const char *label, const char *pin,
  619. isc_mem_t *mctx, dst_key_t **keyp)
  620. {
  621. dst_key_t *key;
  622. isc_result_t result;
  623. REQUIRE(dst_initialized == ISC_TRUE);
  624. REQUIRE(dns_name_isabsolute(name));
  625. REQUIRE(mctx != NULL);
  626. REQUIRE(keyp != NULL && *keyp == NULL);
  627. REQUIRE(label != NULL);
  628. CHECKALG(alg);
  629. key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
  630. if (key == NULL)
  631. return (ISC_R_NOMEMORY);
  632. if (key->func->fromlabel == NULL) {
  633. dst_key_free(&key);
  634. return (DST_R_UNSUPPORTEDALG);
  635. }
  636. result = key->func->fromlabel(key, engine, label, pin);
  637. if (result != ISC_R_SUCCESS) {
  638. dst_key_free(&key);
  639. return (result);
  640. }
  641. result = computeid(key);
  642. if (result != ISC_R_SUCCESS) {
  643. dst_key_free(&key);
  644. return (result);
  645. }
  646. *keyp = key;
  647. return (ISC_R_SUCCESS);
  648. }
  649. isc_result_t
  650. dst_key_generate(dns_name_t *name, unsigned int alg,
  651. unsigned int bits, unsigned int param,
  652. unsigned int flags, unsigned int protocol,
  653. dns_rdataclass_t rdclass,
  654. isc_mem_t *mctx, dst_key_t **keyp)
  655. {
  656. return (dst_key_generate2(name, alg, bits, param, flags, protocol,
  657. rdclass, mctx, keyp, NULL));
  658. }
  659. isc_result_t
  660. dst_key_generate2(dns_name_t *name, unsigned int alg,
  661. unsigned int bits, unsigned int param,
  662. unsigned int flags, unsigned int protocol,
  663. dns_rdataclass_t rdclass,
  664. isc_mem_t *mctx, dst_key_t **keyp,
  665. void (*callback)(int))
  666. {
  667. dst_key_t *key;
  668. isc_result_t ret;
  669. REQUIRE(dst_initialized == ISC_TRUE);
  670. REQUIRE(dns_name_isabsolute(name));
  671. REQUIRE(mctx != NULL);
  672. REQUIRE(keyp != NULL && *keyp == NULL);
  673. CHECKALG(alg);
  674. key = get_key_struct(name, alg, flags, protocol, bits, rdclass, mctx);
  675. if (key == NULL)
  676. return (ISC_R_NOMEMORY);
  677. if (bits == 0) { /*%< NULL KEY */
  678. key->key_flags |= DNS_KEYTYPE_NOKEY;
  679. *keyp = key;
  680. return (ISC_R_SUCCESS);
  681. }
  682. if (key->func->generate == NULL) {
  683. dst_key_free(&key);
  684. return (DST_R_UNSUPPORTEDALG);
  685. }
  686. ret = key->func->generate(key, param, callback);
  687. if (ret != ISC_R_SUCCESS) {
  688. dst_key_free(&key);
  689. return (ret);
  690. }
  691. ret = computeid(key);
  692. if (ret != ISC_R_SUCCESS) {
  693. dst_key_free(&key);
  694. return (ret);
  695. }
  696. *keyp = key;
  697. return (ISC_R_SUCCESS);
  698. }
  699. isc_result_t
  700. dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep)
  701. {
  702. REQUIRE(VALID_KEY(key));
  703. REQUIRE(valuep != NULL);
  704. REQUIRE(type <= DST_MAX_NUMERIC);
  705. if (!key->numset[type])
  706. return (ISC_R_NOTFOUND);
  707. *valuep = key->nums[type];
  708. return (ISC_R_SUCCESS);
  709. }
  710. void
  711. dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value)
  712. {
  713. REQUIRE(VALID_KEY(key));
  714. REQUIRE(type <= DST_MAX_NUMERIC);
  715. key->nums[type] = value;
  716. key->numset[type] = ISC_TRUE;
  717. }
  718. void
  719. dst_key_unsetnum(dst_key_t *key, int type)
  720. {
  721. REQUIRE(VALID_KEY(key));
  722. REQUIRE(type <= DST_MAX_NUMERIC);
  723. key->numset[type] = ISC_FALSE;
  724. }
  725. isc_result_t
  726. dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
  727. REQUIRE(VALID_KEY(key));
  728. REQUIRE(timep != NULL);
  729. REQUIRE(type <= DST_MAX_TIMES);
  730. if (!key->timeset[type])
  731. return (ISC_R_NOTFOUND);
  732. *timep = key->times[type];
  733. return (ISC_R_SUCCESS);
  734. }
  735. void
  736. dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
  737. REQUIRE(VALID_KEY(key));
  738. REQUIRE(type <= DST_MAX_TIMES);
  739. key->times[type] = when;
  740. key->timeset[type] = ISC_TRUE;
  741. }
  742. void
  743. dst_key_unsettime(dst_key_t *key, int type) {
  744. REQUIRE(VALID_KEY(key));
  745. REQUIRE(type <= DST_MAX_TIMES);
  746. key->timeset[type] = ISC_FALSE;
  747. }
  748. isc_result_t
  749. dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
  750. REQUIRE(VALID_KEY(key));
  751. REQUIRE(majorp != NULL);
  752. REQUIRE(minorp != NULL);
  753. *majorp = key->fmt_major;
  754. *minorp = key->fmt_minor;
  755. return (ISC_R_SUCCESS);
  756. }
  757. void
  758. dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
  759. REQUIRE(VALID_KEY(key));
  760. key->fmt_major = major;
  761. key->fmt_minor = minor;
  762. }
  763. static isc_boolean_t
  764. comparekeys(const dst_key_t *key1, const dst_key_t *key2,
  765. isc_boolean_t match_revoked_key,
  766. isc_boolean_t (*compare)(const dst_key_t *key1,
  767. const dst_key_t *key2))
  768. {
  769. REQUIRE(dst_initialized == ISC_TRUE);
  770. REQUIRE(VALID_KEY(key1));
  771. REQUIRE(VALID_KEY(key2));
  772. if (key1 == key2)
  773. return (ISC_TRUE);
  774. if (key1 == NULL || key2 == NULL)
  775. return (ISC_FALSE);
  776. if (key1->key_alg != key2->key_alg)
  777. return (ISC_FALSE);
  778. if (key1->key_id != key2->key_id) {
  779. if (!match_revoked_key)
  780. return (ISC_FALSE);
  781. if (key1->key_alg == DST_ALG_RSAMD5)
  782. return (ISC_FALSE);
  783. if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
  784. (key2->key_flags & DNS_KEYFLAG_REVOKE))
  785. return (ISC_FALSE);
  786. if (key1->key_id != key2->key_rid &&
  787. key1->key_rid != key2->key_id)
  788. return (ISC_FALSE);
  789. }
  790. if (compare != NULL)
  791. return (compare(key1, key2));
  792. else
  793. return (ISC_FALSE);
  794. }
  795. /*
  796. * Compares only the public portion of two keys, by converting them
  797. * both to wire format and comparing the results.
  798. */
  799. static isc_boolean_t
  800. pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
  801. isc_result_t result;
  802. unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
  803. isc_buffer_t b1, b2;
  804. isc_region_t r1, r2;
  805. isc_buffer_init(&b1, buf1, sizeof(buf1));
  806. result = dst_key_todns(key1, &b1);
  807. if (result != ISC_R_SUCCESS)
  808. return (ISC_FALSE);
  809. /* Zero out flags. */
  810. buf1[0] = buf1[1] = 0;
  811. if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
  812. isc_buffer_subtract(&b1, 2);
  813. isc_buffer_init(&b2, buf2, sizeof(buf2));
  814. result = dst_key_todns(key2, &b2);
  815. if (result != ISC_R_SUCCESS)
  816. return (ISC_FALSE);
  817. /* Zero out flags. */
  818. buf2[0] = buf2[1] = 0;
  819. if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
  820. isc_buffer_subtract(&b2, 2);
  821. isc_buffer_usedregion(&b1, &r1);
  822. /* Remove extended flags. */
  823. if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
  824. memmove(&buf1[4], &buf1[6], r1.length - 6);
  825. r1.length -= 2;
  826. }
  827. isc_buffer_usedregion(&b2, &r2);
  828. /* Remove extended flags. */
  829. if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
  830. memmove(&buf2[4], &buf2[6], r2.length - 6);
  831. r2.length -= 2;
  832. }
  833. return (ISC_TF(isc_region_compare(&r1, &r2) == 0));
  834. }
  835. isc_boolean_t
  836. dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
  837. return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare));
  838. }
  839. isc_boolean_t
  840. dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
  841. isc_boolean_t match_revoked_key)
  842. {
  843. return (comparekeys(key1, key2, match_revoked_key, pub_compare));
  844. }
  845. isc_boolean_t
  846. dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
  847. REQUIRE(dst_initialized == ISC_TRUE);
  848. REQUIRE(VALID_KEY(key1));
  849. REQUIRE(VALID_KEY(key2));
  850. if (key1 == key2)
  851. return (ISC_TRUE);
  852. if (key1 == NULL || key2 == NULL)
  853. return (ISC_FALSE);
  854. if (key1->key_alg == key2->key_alg &&
  855. key1->func->paramcompare != NULL &&
  856. key1->func->paramcompare(key1, key2) == ISC_TRUE)
  857. return (ISC_TRUE);
  858. else
  859. return (ISC_FALSE);
  860. }
  861. void
  862. dst_key_attach(dst_key_t *source, dst_key_t **target) {
  863. REQUIRE(dst_initialized == ISC_TRUE);
  864. REQUIRE(target != NULL && *target == NULL);
  865. REQUIRE(VALID_KEY(source));
  866. isc_refcount_increment(&source->refs, NULL);
  867. *target = source;
  868. }
  869. void
  870. dst_key_free(dst_key_t **keyp) {
  871. isc_mem_t *mctx;
  872. dst_key_t *key;
  873. unsigned int refs;
  874. REQUIRE(dst_initialized == ISC_TRUE);
  875. REQUIRE(keyp != NULL && VALID_KEY(*keyp));
  876. key = *keyp;
  877. mctx = key->mctx;
  878. isc_refcount_decrement(&key->refs, &refs);
  879. if (refs != 0)
  880. return;
  881. isc_refcount_destroy(&key->refs);
  882. if (key->keydata.generic != NULL) {
  883. INSIST(key->func->destroy != NULL);
  884. key->func->destroy(key);
  885. }
  886. if (key->engine != NULL)
  887. isc_mem_free(mctx, key->engine);
  888. if (key->label != NULL)
  889. isc_mem_free(mctx, key->label);
  890. dns_name_free(key->key_name, mctx);
  891. isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
  892. if (key->key_tkeytoken) {
  893. isc_buffer_free(&key->key_tkeytoken);
  894. }
  895. memset(key, 0, sizeof(dst_key_t));
  896. isc_mem_put(mctx, key, sizeof(dst_key_t));
  897. *keyp = NULL;
  898. }
  899. isc_boolean_t
  900. dst_key_isprivate(const dst_key_t *key) {
  901. REQUIRE(VALID_KEY(key));
  902. INSIST(key->func->isprivate != NULL);
  903. return (key->func->isprivate(key));
  904. }
  905. isc_result_t
  906. dst_key_buildfilename(const dst_key_t *key, int type,
  907. const char *directory, isc_buffer_t *out) {
  908. REQUIRE(VALID_KEY(key));
  909. REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
  910. type == 0);
  911. return (buildfilename(key->key_name, key->key_id, key->key_alg,
  912. type, directory, out));
  913. }
  914. isc_result_t
  915. dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
  916. REQUIRE(dst_initialized == ISC_TRUE);
  917. REQUIRE(VALID_KEY(key));
  918. REQUIRE(n != NULL);
  919. /* XXXVIX this switch statement is too sparse to gen a jump table. */
  920. switch (key->key_alg) {
  921. case DST_ALG_RSAMD5:
  922. case DST_ALG_RSASHA1:
  923. case DST_ALG_NSEC3RSASHA1:
  924. case DST_ALG_RSASHA256:
  925. case DST_ALG_RSASHA512:
  926. *n = (key->key_size + 7) / 8;
  927. break;
  928. case DST_ALG_DSA:
  929. case DST_ALG_NSEC3DSA:
  930. *n = DNS_SIG_DSASIGSIZE;
  931. break;
  932. case DST_ALG_ECCGOST:
  933. *n = DNS_SIG_GOSTSIGSIZE;
  934. break;
  935. case DST_ALG_HMACMD5:
  936. *n = 16;
  937. break;
  938. case DST_ALG_HMACSHA1:
  939. *n = ISC_SHA1_DIGESTLENGTH;
  940. break;
  941. case DST_ALG_HMACSHA224:
  942. *n = ISC_SHA224_DIGESTLENGTH;
  943. break;
  944. case DST_ALG_HMACSHA256:
  945. *n = ISC_SHA256_DIGESTLENGTH;
  946. break;
  947. case DST_ALG_HMACSHA384:
  948. *n = ISC_SHA384_DIGESTLENGTH;
  949. break;
  950. case DST_ALG_HMACSHA512:
  951. *n = ISC_SHA512_DIGESTLENGTH;
  952. break;
  953. case DST_ALG_GSSAPI:
  954. *n = 128; /*%< XXX */
  955. break;
  956. case DST_ALG_DH:
  957. default:
  958. return (DST_R_UNSUPPORTEDALG);
  959. }
  960. return (ISC_R_SUCCESS);
  961. }
  962. isc_result_t
  963. dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
  964. REQUIRE(dst_initialized == ISC_TRUE);
  965. REQUIRE(VALID_KEY(key));
  966. REQUIRE(n != NULL);
  967. if (key->key_alg == DST_ALG_DH)
  968. *n = (key->key_size + 7) / 8;
  969. else
  970. return (DST_R_UNSUPPORTEDALG);
  971. return (ISC_R_SUCCESS);
  972. }
  973. /*%
  974. * Set the flags on a key, then recompute the key ID
  975. */
  976. isc_result_t
  977. dst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
  978. REQUIRE(VALID_KEY(key));
  979. key->key_flags = flags;
  980. return (computeid(key));
  981. }
  982. void
  983. dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
  984. char namestr[DNS_NAME_FORMATSIZE];
  985. char algstr[DNS_NAME_FORMATSIZE];
  986. dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
  987. dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr,
  988. sizeof(algstr));
  989. snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
  990. }
  991. isc_result_t
  992. dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
  993. REQUIRE(buffer != NULL && *buffer == NULL);
  994. REQUIRE(length != NULL && *length == 0);
  995. REQUIRE(VALID_KEY(key));
  996. if (key->func->isprivate == NULL)
  997. return (ISC_R_NOTIMPLEMENTED);
  998. return (key->func->dump(key, mctx, buffer, length));
  999. }
  1000. isc_result_t
  1001. dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
  1002. unsigned int protocol, dns_rdataclass_t rdclass,
  1003. isc_mem_t *mctx, const char *keystr, dst_key_t **keyp)
  1004. {
  1005. isc_result_t result;
  1006. dst_key_t *key;
  1007. REQUIRE(dst_initialized == ISC_TRUE);
  1008. REQUIRE(keyp != NULL && *keyp == NULL);
  1009. if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
  1010. return (DST_R_UNSUPPORTEDALG);
  1011. if (dst_t_func[alg]->restore == NULL)
  1012. return (ISC_R_NOTIMPLEMENTED);
  1013. key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
  1014. if (key == NULL)
  1015. return (ISC_R_NOMEMORY);
  1016. result = (dst_t_func[alg]->restore)(key, keystr);
  1017. if (result == ISC_R_SUCCESS)
  1018. *keyp = key;
  1019. else
  1020. dst_key_free(&key);
  1021. return (result);
  1022. }
  1023. /***
  1024. *** Static methods
  1025. ***/
  1026. /*%
  1027. * Allocates a key structure and fills in some of the fields.
  1028. */
  1029. static dst_key_t *
  1030. get_key_struct(dns_name_t *name, unsigned int alg,
  1031. unsigned int flags, unsigned int protocol,
  1032. unsigned int bits, dns_rdataclass_t rdclass,
  1033. isc_mem_t *mctx)
  1034. {
  1035. dst_key_t *key;
  1036. isc_result_t result;
  1037. int i;
  1038. key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
  1039. if (key == NULL)
  1040. return (NULL);
  1041. memset(key, 0, sizeof(dst_key_t));
  1042. key->magic = KEY_MAGIC;
  1043. result = isc_refcount_init(&key->refs, 1);
  1044. if (result != ISC_R_SUCCESS) {
  1045. isc_mem_put(mctx, key, sizeof(dst_key_t));
  1046. return (NULL);
  1047. }
  1048. key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
  1049. if (key->key_name == NULL) {
  1050. isc_refcount_destroy(&key->refs);
  1051. isc_mem_put(mctx, key, sizeof(dst_key_t));
  1052. return (NULL);
  1053. }
  1054. dns_name_init(key->key_name, NULL);
  1055. result = dns_name_dup(name, mctx, key->key_name);
  1056. if (result != ISC_R_SUCCESS) {
  1057. isc_refcount_destroy(&key->refs);
  1058. isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
  1059. isc_mem_put(mctx, key, sizeof(dst_key_t));
  1060. return (NULL);
  1061. }
  1062. key->key_alg = alg;
  1063. key->key_flags = flags;
  1064. key->key_proto = protocol;
  1065. key->mctx = mctx;
  1066. key->keydata.generic = NULL;
  1067. key->key_size = bits;
  1068. key->key_class = rdclass;
  1069. key->func = dst_t_func[alg];
  1070. key->fmt_major = 0;
  1071. key->fmt_minor = 0;
  1072. for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
  1073. key->times[i] = 0;
  1074. key->timeset[i] = ISC_FALSE;
  1075. }
  1076. return (key);
  1077. }
  1078. /*%
  1079. * Reads a public key from disk
  1080. */
  1081. isc_result_t
  1082. dst_key_read_public(const char *filename, int type,
  1083. isc_mem_t *mctx, dst_key_t **keyp)
  1084. {
  1085. u_char rdatabuf[DST_KEY_MAXSIZE];
  1086. isc_buffer_t b;
  1087. dns_fixedname_t name;
  1088. isc_lex_t *lex = NULL;
  1089. isc_token_t token;
  1090. isc_result_t ret;
  1091. dns_rdata_t rdata = DNS_RDATA_INIT;
  1092. unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
  1093. dns_rdataclass_t rdclass = dns_rdataclass_in;
  1094. isc_lexspecials_t specials;
  1095. isc_uint32_t ttl;
  1096. isc_result_t result;
  1097. dns_rdatatype_t keytype;
  1098. /*
  1099. * Open the file and read its formatted contents
  1100. * File format:
  1101. * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
  1102. */
  1103. /* 1500 should be large enough for any key */
  1104. ret = isc_lex_create(mctx, 1500, &lex);
  1105. if (ret != ISC_R_SUCCESS)
  1106. goto cleanup;
  1107. memset(specials, 0, sizeof(specials));
  1108. specials['('] = 1;
  1109. specials[')'] = 1;
  1110. specials['"'] = 1;
  1111. isc_lex_setspecials(lex, specials);
  1112. isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
  1113. ret = isc_lex_openfile(lex, filename);
  1114. if (ret != ISC_R_SUCCESS)
  1115. goto cleanup;
  1116. #define NEXTTOKEN(lex, opt, token) { \
  1117. ret = isc_lex_gettoken(lex, opt, token); \
  1118. if (ret != ISC_R_SUCCESS) \
  1119. goto cleanup; \
  1120. }
  1121. #define BADTOKEN() { \
  1122. ret = ISC_R_UNEXPECTEDTOKEN; \
  1123. goto cleanup; \
  1124. }
  1125. /* Read the domain name */
  1126. NEXTTOKEN(lex, opt, &token);
  1127. if (token.type != isc_tokentype_string)
  1128. BADTOKEN();
  1129. /*
  1130. * We don't support "@" in .key files.
  1131. */
  1132. if (!strcmp(DST_AS_STR(token), "@"))
  1133. BADTOKEN();
  1134. dns_fixedname_init(&name);
  1135. isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
  1136. isc_buffer_add(&b, strlen(DST_AS_STR(token)));
  1137. ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
  1138. 0, NULL);
  1139. if (ret != ISC_R_SUCCESS)
  1140. goto cleanup;
  1141. /* Read the next word: either TTL, class, or 'KEY' */
  1142. NEXTTOKEN(lex, opt, &token);
  1143. if (token.type != isc_tokentype_string)
  1144. BADTOKEN();
  1145. /* If it's a TTL, read the next one */
  1146. result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
  1147. if (result == ISC_R_SUCCESS)
  1148. NEXTTOKEN(lex, opt, &token);
  1149. if (token.type != isc_tokentype_string)
  1150. BADTOKEN();
  1151. ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
  1152. if (ret == ISC_R_SUCCESS)
  1153. NEXTTOKEN(lex, opt, &token);
  1154. if (token.type != isc_tokentype_string)
  1155. BADTOKEN();
  1156. if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
  1157. keytype = dns_rdatatype_dnskey;
  1158. else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
  1159. keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
  1160. else
  1161. BADTOKEN();
  1162. if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
  1163. ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
  1164. ret = DST_R_BADKEYTYPE;
  1165. goto cleanup;
  1166. }
  1167. isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
  1168. ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
  1169. ISC_FALSE, mctx, &b, NULL);
  1170. if (ret != ISC_R_SUCCESS)
  1171. goto cleanup;
  1172. ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
  1173. keyp);
  1174. if (ret != ISC_R_SUCCESS)
  1175. goto cleanup;
  1176. cleanup:
  1177. if (lex != NULL)
  1178. isc_lex_destroy(&lex);
  1179. return (ret);
  1180. }
  1181. static isc_boolean_t
  1182. issymmetric(const dst_key_t *key) {
  1183. REQUIRE(dst_initialized == ISC_TRUE);
  1184. REQUIRE(VALID_KEY(key));
  1185. /* XXXVIX this switch statement is too sparse to gen a jump table. */
  1186. switch (key->key_alg) {
  1187. case DST_ALG_RSAMD5:
  1188. case DST_ALG_RSASHA1:
  1189. case DST_ALG_NSEC3RSASHA1:
  1190. case DST_ALG_RSASHA256:
  1191. case DST_ALG_RSASHA512:
  1192. case DST_ALG_DSA:
  1193. case DST_ALG_NSEC3DSA:
  1194. case DST_ALG_DH:
  1195. case DST_ALG_ECCGOST:
  1196. return (ISC_FALSE);
  1197. case DST_ALG_HMACMD5:
  1198. case DST_ALG_GSSAPI:
  1199. return (ISC_TRUE);
  1200. default:
  1201. return (ISC_FALSE);
  1202. }
  1203. }
  1204. /*%
  1205. * Write key timing metadata to a file pointer, preceded by 'tag'
  1206. */
  1207. static void
  1208. printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
  1209. isc_result_t result;
  1210. #ifdef ISC_PLATFORM_USETHREADS
  1211. char output[26]; /* Minimum buffer as per ctime_r() specification. */
  1212. #else
  1213. const char *output;
  1214. #endif
  1215. isc_stdtime_t when;
  1216. time_t t;
  1217. char utc[sizeof("YYYYMMDDHHSSMM")];
  1218. isc_buffer_t b;
  1219. isc_region_t r;
  1220. result = dst_key_gettime(key, type, &when);
  1221. if (result == ISC_R_NOTFOUND)
  1222. return;
  1223. /* time_t and isc_stdtime_t might be different sizes */
  1224. t = when;
  1225. #ifdef ISC_PLATFORM_USETHREADS
  1226. #ifdef WIN32
  1227. if (ctime_s(output, sizeof(output), &t) != 0)
  1228. goto error;
  1229. #else
  1230. if (ctime_r(&t, output) == NULL)
  1231. goto error;
  1232. #endif
  1233. #else
  1234. output = ctime(&t);
  1235. #endif
  1236. isc_buffer_init(&b, utc, sizeof(utc));
  1237. result = dns_time32_totext(when, &b);
  1238. if (result != ISC_R_SUCCESS)
  1239. goto error;
  1240. isc_buffer_usedregion(&b, &r);
  1241. fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
  1242. (int)strlen(output) - 1, output);
  1243. return;
  1244. error:
  1245. fprintf(stream, "%s: (set, unable to display)\n", tag);
  1246. }
  1247. /*%
  1248. * Writes a public key to disk in DNS format.
  1249. */
  1250. static isc_result_t
  1251. write_public_key(const dst_key_t *key, int type, const char *directory) {
  1252. FILE *fp;
  1253. isc_buffer_t keyb, textb, fileb, classb;
  1254. isc_region_t r;
  1255. char filename[ISC_DIR_NAMEMAX];
  1256. unsigned char key_array[DST_KEY_MAXSIZE];
  1257. char text_array[DST_KEY_MAXTEXTSIZE];
  1258. char class_array[10];
  1259. isc_result_t ret;
  1260. dns_rdata_t rdata = DNS_RDATA_INIT;
  1261. isc_fsaccess_t access;
  1262. REQUIRE(VALID_KEY(key));
  1263. isc_buffer_init(&keyb, key_array, sizeof(key_array));
  1264. isc_buffer_init(&textb, text_array, sizeof(text_array));
  1265. isc_buffer_init(&classb, class_array, sizeof(class_array));
  1266. ret = dst_key_todns(key, &keyb);
  1267. if (ret != ISC_R_SUCCESS)
  1268. return (ret);
  1269. isc_buffer_usedregion(&keyb, &r);
  1270. dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
  1271. ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
  1272. if (ret != ISC_R_SUCCESS)
  1273. return (DST_R_INVALIDPUBLICKEY);
  1274. ret = dns_rdataclass_totext(key->key_class, &classb);
  1275. if (ret != ISC_R_SUCCESS)
  1276. return (DST_R_INVALIDPUBLICKEY);
  1277. /*
  1278. * Make the filename.
  1279. */
  1280. isc_buffer_init(&fileb, filename, sizeof(filename));
  1281. ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
  1282. if (ret != ISC_R_SUCCESS)
  1283. return (ret);
  1284. /*
  1285. * Create public key file.
  1286. */
  1287. if ((fp = fopen(filename, "w")) == NULL)
  1288. return (DST_R_WRITEERROR);
  1289. if (issymmetric(key)) {
  1290. access = 0;
  1291. isc_fsaccess_add(ISC_FSACCESS_OWNER,
  1292. ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
  1293. &access);
  1294. (void)isc_fsaccess_set(filename, access);
  1295. }
  1296. /* Write key information in comments */
  1297. if ((type & DST_TYPE_KEY) == 0) {
  1298. fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
  1299. (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
  1300. "revoked " :
  1301. "",
  1302. (key->key_flags & DNS_KEYFLAG_KSK) != 0 ?
  1303. "key" :
  1304. "zone",
  1305. key->key_id);
  1306. ret = dns_name_print(key->key_name, fp);
  1307. if (ret != ISC_R_SUCCESS) {
  1308. fclose(fp);
  1309. return (ret);
  1310. }
  1311. fputc('\n', fp);
  1312. printtime(key, DST_TIME_CREATED, "; Created", fp);
  1313. printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
  1314. printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
  1315. printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
  1316. printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
  1317. printtime(key, DST_TIME_DELETE, "; Delete", fp);
  1318. }
  1319. /* Now print the actual key */
  1320. ret = dns_name_print(key->key_name, fp);
  1321. fprintf(fp, " ");
  1322. isc_buffer_usedregion(&classb, &r);
  1323. if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
  1324. ret = DST_R_WRITEERROR;
  1325. if ((type & DST_TYPE_KEY) != 0)
  1326. fprintf(fp, " KEY ");
  1327. else
  1328. fprintf(fp, " DNSKEY ");
  1329. isc_buffer_usedregion(&textb, &r);
  1330. if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
  1331. ret = DST_R_WRITEERROR;
  1332. fputc('\n', fp);
  1333. fflush(fp);
  1334. if (ferror(fp))
  1335. ret = DST_R_WRITEERROR;
  1336. fclose(fp);
  1337. return (ret);
  1338. }
  1339. static isc_result_t
  1340. buildfilename(dns_name_t *name, dns_keytag_t id,
  1341. unsigned int alg, unsigned int type,
  1342. const char *directory, isc_buffer_t *out)
  1343. {
  1344. const char *suffix = "";
  1345. unsigned int len;
  1346. isc_result_t result;
  1347. REQUIRE(out != NULL);
  1348. if ((type & DST_TYPE_PRIVATE) != 0)
  1349. suffix = ".private";
  1350. else if (type == DST_TYPE_PUBLIC)
  1351. suffix = ".key";
  1352. if (directory != NULL) {
  1353. if (isc_buffer_availablelength(out) < strlen(directory))
  1354. return (ISC_R_NOSPACE);
  1355. isc_buffer_putstr(out, directory);
  1356. if (strlen(directory) > 0U &&
  1357. directory[strlen(directory) - 1] != '/')
  1358. isc_buffer_putstr(out, "/");
  1359. }
  1360. if (isc_buffer_availablelength(out) < 1)
  1361. return (ISC_R_NOSPACE);
  1362. isc_buffer_putstr(out, "K");
  1363. result = dns_name_tofilenametext(name, ISC_FALSE, out);
  1364. if (result != ISC_R_SUCCESS)
  1365. return (result);
  1366. len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
  1367. if (isc_buffer_availablelength(out) < len)
  1368. return (ISC_R_NOSPACE);
  1369. sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
  1370. suffix);
  1371. isc_buffer_add(out, len);
  1372. return (ISC_R_SUCCESS);
  1373. }
  1374. static isc_result_t
  1375. computeid(dst_key_t *key) {
  1376. isc_buffer_t dnsbuf;
  1377. unsigned char dns_array[DST_KEY_MAXSIZE];
  1378. isc_region_t r;
  1379. isc_result_t ret;
  1380. isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
  1381. ret = dst_key_todns(key, &dnsbuf);
  1382. if (ret != ISC_R_SUCCESS)
  1383. return (ret);
  1384. isc_buffer_usedregion(&dnsbuf, &r);
  1385. key->key_id = dst_region_computeid(&r, key->key_alg);
  1386. key->key_rid = dst_region_computerid(&r, key->key_alg);
  1387. return (ISC_R_SUCCESS);
  1388. }
  1389. static isc_result_t
  1390. frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags,
  1391. unsigned int protocol, dns_rdataclass_t rdclass,
  1392. isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
  1393. {
  1394. dst_key_t *key;
  1395. isc_result_t ret;
  1396. REQUIRE(dns_name_isabsolute(name));
  1397. REQUIRE(source != NULL);
  1398. REQUIRE(mctx != NULL);
  1399. REQUIRE(keyp != NULL && *keyp == NULL);
  1400. key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
  1401. if (key == NULL)
  1402. return (ISC_R_NOMEMORY);
  1403. if (isc_buffer_remaininglength(source) > 0) {
  1404. ret = algorithm_status(alg);
  1405. if (ret != ISC_R_SUCCESS) {
  1406. dst_key_free(&key);
  1407. return (ret);
  1408. }
  1409. if (key->func->fromdns == NULL) {
  1410. dst_key_free(&key);
  1411. return (DST_R_UNSUPPORTEDALG);
  1412. }
  1413. ret = key->func->fromdns(key, source);
  1414. if (ret != ISC_R_SUCCESS) {
  1415. dst_key_free(&key);
  1416. return (ret);
  1417. }
  1418. }
  1419. *keyp = key;
  1420. return (ISC_R_SUCCESS);
  1421. }
  1422. static isc_result_t
  1423. algorithm_status(unsigned int alg) {
  1424. REQUIRE(dst_initialized == ISC_TRUE);
  1425. if (dst_algorithm_supported(alg))
  1426. return (ISC_R_SUCCESS);
  1427. #ifndef OPENSSL
  1428. if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
  1429. alg == DST_ALG_DSA || alg == DST_ALG_DH ||
  1430. alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
  1431. alg == DST_ALG_NSEC3RSASHA1 ||
  1432. alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 ||
  1433. alg == DST_ALG_ECCGOST)
  1434. return (DST_R_NOCRYPTO);
  1435. #endif
  1436. return (DST_R_UNSUPPORTEDALG);
  1437. }
  1438. static isc_result_t
  1439. addsuffix(char *filename, int len, const char *odirname,
  1440. const char *ofilename, const char *suffix)
  1441. {
  1442. int olen = strlen(ofilename);
  1443. int n;
  1444. if (olen > 1 && ofilename[olen - 1] == '.')
  1445. olen -= 1;
  1446. else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0)
  1447. olen -= 8;
  1448. else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
  1449. olen -= 4;
  1450. if (odirname == NULL)
  1451. n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
  1452. else
  1453. n = snprintf(filename, len, "%s/%.*s%s",
  1454. odirname, olen, ofilename, suffix);
  1455. if (n < 0)
  1456. return (ISC_R_FAILURE);
  1457. if (n >= len)
  1458. return (ISC_R_NOSPACE);
  1459. return (ISC_R_SUCCESS);
  1460. }
  1461. isc_result_t
  1462. dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
  1463. #ifdef BIND9
  1464. unsigned int flags = dst_entropy_flags;
  1465. if (len == 0)
  1466. return (ISC_R_SUCCESS);
  1467. if (pseudo)
  1468. flags &= ~ISC_ENTROPY_GOODONLY;
  1469. else
  1470. flags |= ISC_ENTROPY_BLOCKING;
  1471. return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
  1472. #else
  1473. UNUSED(buf);
  1474. UNUSED(len);
  1475. UNUSED(pseudo);
  1476. return (ISC_R_NOTIMPLEMENTED);
  1477. #endif
  1478. }
  1479. unsigned int
  1480. dst__entropy_status(void) {
  1481. #ifdef BIND9
  1482. #ifdef GSSAPI
  1483. unsigned int flags = dst_entropy_flags;
  1484. isc_result_t ret;
  1485. unsigned char buf[32];
  1486. static isc_boolean_t first = ISC_TRUE;
  1487. if (first) {
  1488. /* Someone believes RAND_status() initializes the PRNG */
  1489. flags &= ~ISC_ENTROPY_GOODONLY;
  1490. ret = isc_entropy_getdata(dst_entropy_pool, buf,
  1491. sizeof(buf), NULL, flags);
  1492. INSIST(ret == ISC_R_SUCCESS);
  1493. isc_entropy_putdata(dst_entropy_pool, buf,
  1494. sizeof(buf), 2 * sizeof(buf));
  1495. first = ISC_FALSE;
  1496. }
  1497. #endif
  1498. return (isc_entropy_status(dst_entropy_pool));
  1499. #else
  1500. return (0);
  1501. #endif
  1502. }
  1503. isc_buffer_t *
  1504. dst_key_tkeytoken(const dst_key_t *key) {
  1505. REQUIRE(VALID_KEY(key));
  1506. return (key->key_tkeytoken);
  1507. }