Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / dst_parse.c
blob87946f66fd932eb67028c350fd5171c3dc25aeab
1 /* $NetBSD: dst_parse.c,v 1.8 2014/12/10 04:37:58 christos Exp $ */
3 /*
4 * Portions Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 /*%
35 * Principal Author: Brian Wellington
36 * Id: dst_parse.c,v 1.29 2011/08/18 23:46:35 tbox Exp
39 #include <config.h>
41 #include <isc/base64.h>
42 #include <isc/dir.h>
43 #include <isc/fsaccess.h>
44 #include <isc/lex.h>
45 #include <isc/mem.h>
46 #include <isc/stdtime.h>
47 #include <isc/string.h>
48 #include <isc/util.h>
49 #include <isc/file.h>
51 #include <dns/time.h>
52 #include <dns/log.h>
54 #include "dst_internal.h"
55 #include "dst_parse.h"
56 #include "dst/result.h"
58 #define DST_AS_STR(t) ((t).value.as_textregion.base)
60 #define PRIVATE_KEY_STR "Private-key-format:"
61 #define ALGORITHM_STR "Algorithm:"
63 #define TIMING_NTAGS (DST_MAX_TIMES + 1)
64 static const char *timetags[TIMING_NTAGS] = {
65 "Created:",
66 "Publish:",
67 "Activate:",
68 "Revoke:",
69 "Inactive:",
70 "Delete:",
71 "DSPublish:"
74 #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
75 static const char *numerictags[NUMERIC_NTAGS] = {
76 "Predecessor:",
77 "Successor:",
78 "MaxTTL:",
79 "RollPeriod:"
82 struct parse_map {
83 const int value;
84 const char *tag;
87 static struct parse_map map[] = {
88 {TAG_RSA_MODULUS, "Modulus:"},
89 {TAG_RSA_PUBLICEXPONENT, "PublicExponent:"},
90 {TAG_RSA_PRIVATEEXPONENT, "PrivateExponent:"},
91 {TAG_RSA_PRIME1, "Prime1:"},
92 {TAG_RSA_PRIME2, "Prime2:"},
93 {TAG_RSA_EXPONENT1, "Exponent1:"},
94 {TAG_RSA_EXPONENT2, "Exponent2:"},
95 {TAG_RSA_COEFFICIENT, "Coefficient:"},
96 {TAG_RSA_ENGINE, "Engine:" },
97 {TAG_RSA_LABEL, "Label:" },
99 {TAG_DH_PRIME, "Prime(p):"},
100 {TAG_DH_GENERATOR, "Generator(g):"},
101 {TAG_DH_PRIVATE, "Private_value(x):"},
102 {TAG_DH_PUBLIC, "Public_value(y):"},
104 {TAG_DSA_PRIME, "Prime(p):"},
105 {TAG_DSA_SUBPRIME, "Subprime(q):"},
106 {TAG_DSA_BASE, "Base(g):"},
107 {TAG_DSA_PRIVATE, "Private_value(x):"},
108 {TAG_DSA_PUBLIC, "Public_value(y):"},
110 {TAG_GOST_PRIVASN1, "GostAsn1:"},
111 {TAG_GOST_PRIVRAW, "PrivateKey:"},
113 {TAG_ECDSA_PRIVATEKEY, "PrivateKey:"},
114 {TAG_ECDSA_ENGINE, "Engine:" },
115 {TAG_ECDSA_LABEL, "Label:" },
117 {TAG_HMACMD5_KEY, "Key:"},
118 {TAG_HMACMD5_BITS, "Bits:"},
120 {TAG_HMACSHA1_KEY, "Key:"},
121 {TAG_HMACSHA1_BITS, "Bits:"},
123 {TAG_HMACSHA224_KEY, "Key:"},
124 {TAG_HMACSHA224_BITS, "Bits:"},
126 {TAG_HMACSHA256_KEY, "Key:"},
127 {TAG_HMACSHA256_BITS, "Bits:"},
129 {TAG_HMACSHA384_KEY, "Key:"},
130 {TAG_HMACSHA384_BITS, "Bits:"},
132 {TAG_HMACSHA512_KEY, "Key:"},
133 {TAG_HMACSHA512_BITS, "Bits:"},
135 {0, NULL}
138 static int
139 find_value(const char *s, const unsigned int alg) {
140 int i;
142 for (i = 0; map[i].tag != NULL; i++) {
143 if (strcasecmp(s, map[i].tag) == 0 &&
144 (TAG_ALG(map[i].value) == alg))
145 return (map[i].value);
147 return (-1);
150 static const char *
151 find_tag(const int value) {
152 int i;
154 for (i = 0; ; i++) {
155 if (map[i].tag == NULL)
156 return (NULL);
157 else if (value == map[i].value)
158 return (map[i].tag);
162 static int
163 find_metadata(const char *s, const char *tags[], int ntags) {
164 int i;
166 for (i = 0; i < ntags; i++) {
167 if (strcasecmp(s, tags[i]) == 0)
168 return (i);
171 return (-1);
174 static int
175 find_timedata(const char *s) {
176 return (find_metadata(s, timetags, TIMING_NTAGS));
179 static int
180 find_numericdata(const char *s) {
181 return (find_metadata(s, numerictags, NUMERIC_NTAGS));
184 static int
185 check_rsa(const dst_private_t *priv, isc_boolean_t external) {
186 int i, j;
187 isc_boolean_t have[RSA_NTAGS];
188 isc_boolean_t ok;
189 unsigned int mask;
191 if (external)
192 return ((priv->nelements == 0) ? 0 : -1);
194 for (i = 0; i < RSA_NTAGS; i++)
195 have[i] = ISC_FALSE;
197 for (j = 0; j < priv->nelements; j++) {
198 for (i = 0; i < RSA_NTAGS; i++)
199 if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i))
200 break;
201 if (i == RSA_NTAGS)
202 return (-1);
203 have[i] = ISC_TRUE;
206 mask = ~0;
207 mask <<= sizeof(mask) * 8 - TAG_SHIFT;
208 mask >>= sizeof(mask) * 8 - TAG_SHIFT;
210 if (have[TAG_RSA_ENGINE & mask])
211 ok = have[TAG_RSA_MODULUS & mask] &&
212 have[TAG_RSA_PUBLICEXPONENT & mask] &&
213 have[TAG_RSA_LABEL & mask];
214 else
215 ok = have[TAG_RSA_MODULUS & mask] &&
216 have[TAG_RSA_PUBLICEXPONENT & mask] &&
217 have[TAG_RSA_PRIVATEEXPONENT & mask] &&
218 have[TAG_RSA_PRIME1 & mask] &&
219 have[TAG_RSA_PRIME2 & mask] &&
220 have[TAG_RSA_EXPONENT1 & mask] &&
221 have[TAG_RSA_EXPONENT2 & mask] &&
222 have[TAG_RSA_COEFFICIENT & mask];
223 return (ok ? 0 : -1 );
226 static int
227 check_dh(const dst_private_t *priv) {
228 int i, j;
229 if (priv->nelements != DH_NTAGS)
230 return (-1);
231 for (i = 0; i < DH_NTAGS; i++) {
232 for (j = 0; j < priv->nelements; j++)
233 if (priv->elements[j].tag == TAG(DST_ALG_DH, i))
234 break;
235 if (j == priv->nelements)
236 return (-1);
238 return (0);
241 static int
242 check_dsa(const dst_private_t *priv, isc_boolean_t external) {
243 int i, j;
245 if (external)
246 return ((priv->nelements == 0)? 0 : -1);
248 if (priv->nelements != DSA_NTAGS)
249 return (-1);
251 for (i = 0; i < DSA_NTAGS; i++) {
252 for (j = 0; j < priv->nelements; j++)
253 if (priv->elements[j].tag == TAG(DST_ALG_DSA, i))
254 break;
255 if (j == priv->nelements)
256 return (-1);
258 return (0);
261 static int
262 check_gost(const dst_private_t *priv, isc_boolean_t external) {
264 if (external)
265 return ((priv->nelements == 0)? 0 : -1);
267 if (priv->nelements != GOST_NTAGS)
268 return (-1);
269 if ((priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) &&
270 (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 1)))
271 return (-1);
272 return (0);
275 static int
276 check_ecdsa(const dst_private_t *priv, isc_boolean_t external) {
277 int i, j;
278 isc_boolean_t have[ECDSA_NTAGS];
279 isc_boolean_t ok;
280 unsigned int mask;
282 if (external)
283 return ((priv->nelements == 0) ? 0 : -1);
285 for (i = 0; i < ECDSA_NTAGS; i++)
286 have[i] = ISC_FALSE;
287 for (j = 0; j < priv->nelements; j++) {
288 for (i = 0; i < ECDSA_NTAGS; i++)
289 if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i))
290 break;
291 if (i == ECDSA_NTAGS)
292 return (-1);
293 have[i] = ISC_TRUE;
296 mask = ~0;
297 mask <<= sizeof(mask) * 8 - TAG_SHIFT;
298 mask >>= sizeof(mask) * 8 - TAG_SHIFT;
300 if (have[TAG_ECDSA_ENGINE & mask])
301 ok = have[TAG_ECDSA_LABEL & mask];
302 else
303 ok = have[TAG_ECDSA_PRIVATEKEY & mask];
304 return (ok ? 0 : -1 );
307 static int
308 check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) {
309 int i, j;
311 if (priv->nelements != HMACMD5_NTAGS) {
313 * If this is a good old format and we are accepting
314 * the old format return success.
316 if (old && priv->nelements == OLD_HMACMD5_NTAGS &&
317 priv->elements[0].tag == TAG_HMACMD5_KEY)
318 return (0);
319 return (-1);
322 * We must be new format at this point.
324 for (i = 0; i < HMACMD5_NTAGS; i++) {
325 for (j = 0; j < priv->nelements; j++)
326 if (priv->elements[j].tag == TAG(DST_ALG_HMACMD5, i))
327 break;
328 if (j == priv->nelements)
329 return (-1);
331 return (0);
334 static int
335 check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
336 unsigned int alg)
338 unsigned int i, j;
339 if (priv->nelements != ntags)
340 return (-1);
341 for (i = 0; i < ntags; i++) {
342 for (j = 0; j < priv->nelements; j++)
343 if (priv->elements[j].tag == TAG(alg, i))
344 break;
345 if (j == priv->nelements)
346 return (-1);
348 return (0);
351 static int
352 check_data(const dst_private_t *priv, const unsigned int alg,
353 isc_boolean_t old, isc_boolean_t external)
355 /* XXXVIX this switch statement is too sparse to gen a jump table. */
356 switch (alg) {
357 case DST_ALG_RSAMD5:
358 case DST_ALG_RSASHA1:
359 case DST_ALG_NSEC3RSASHA1:
360 case DST_ALG_RSASHA256:
361 case DST_ALG_RSASHA512:
362 return (check_rsa(priv, external));
363 case DST_ALG_DH:
364 return (check_dh(priv));
365 case DST_ALG_DSA:
366 case DST_ALG_NSEC3DSA:
367 return (check_dsa(priv, external));
368 case DST_ALG_ECCGOST:
369 return (check_gost(priv, external));
370 case DST_ALG_ECDSA256:
371 case DST_ALG_ECDSA384:
372 return (check_ecdsa(priv, external));
373 case DST_ALG_HMACMD5:
374 return (check_hmac_md5(priv, old));
375 case DST_ALG_HMACSHA1:
376 return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg));
377 case DST_ALG_HMACSHA224:
378 return (check_hmac_sha(priv, HMACSHA224_NTAGS, alg));
379 case DST_ALG_HMACSHA256:
380 return (check_hmac_sha(priv, HMACSHA256_NTAGS, alg));
381 case DST_ALG_HMACSHA384:
382 return (check_hmac_sha(priv, HMACSHA384_NTAGS, alg));
383 case DST_ALG_HMACSHA512:
384 return (check_hmac_sha(priv, HMACSHA512_NTAGS, alg));
385 default:
386 return (DST_R_UNSUPPORTEDALG);
390 void
391 dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) {
392 int i;
394 if (priv == NULL)
395 return;
396 for (i = 0; i < priv->nelements; i++) {
397 if (priv->elements[i].data == NULL)
398 continue;
399 memset(priv->elements[i].data, 0, MAXFIELDSIZE);
400 isc_mem_put(mctx, priv->elements[i].data, MAXFIELDSIZE);
402 priv->nelements = 0;
405 isc_result_t
406 dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
407 isc_mem_t *mctx, dst_private_t *priv)
409 int n = 0, major, minor, check;
410 isc_buffer_t b;
411 isc_token_t token;
412 unsigned char *data = NULL;
413 unsigned int opt = ISC_LEXOPT_EOL;
414 isc_stdtime_t when;
415 isc_result_t ret;
416 isc_boolean_t external = ISC_FALSE;
418 REQUIRE(priv != NULL);
420 priv->nelements = 0;
421 memset(priv->elements, 0, sizeof(priv->elements));
423 #define NEXTTOKEN(lex, opt, token) \
424 do { \
425 ret = isc_lex_gettoken(lex, opt, token); \
426 if (ret != ISC_R_SUCCESS) \
427 goto fail; \
428 } while (/*CONSTCOND*/0)
430 #define READLINE(lex, opt, token) \
431 do { \
432 ret = isc_lex_gettoken(lex, opt, token); \
433 if (ret == ISC_R_EOF) \
434 break; \
435 else if (ret != ISC_R_SUCCESS) \
436 goto fail; \
437 } while ((*token).type != isc_tokentype_eol)
440 * Read the description line.
442 NEXTTOKEN(lex, opt, &token);
443 if (token.type != isc_tokentype_string ||
444 strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0)
446 ret = DST_R_INVALIDPRIVATEKEY;
447 goto fail;
450 NEXTTOKEN(lex, opt, &token);
451 if (token.type != isc_tokentype_string ||
452 (DST_AS_STR(token))[0] != 'v')
454 ret = DST_R_INVALIDPRIVATEKEY;
455 goto fail;
457 if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2)
459 ret = DST_R_INVALIDPRIVATEKEY;
460 goto fail;
463 if (major > DST_MAJOR_VERSION) {
464 ret = DST_R_INVALIDPRIVATEKEY;
465 goto fail;
469 * Store the private key format version number
471 dst_key_setprivateformat(key, major, minor);
473 READLINE(lex, opt, &token);
476 * Read the algorithm line.
478 NEXTTOKEN(lex, opt, &token);
479 if (token.type != isc_tokentype_string ||
480 strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0)
482 ret = DST_R_INVALIDPRIVATEKEY;
483 goto fail;
486 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
487 if (token.type != isc_tokentype_number ||
488 token.value.as_ulong != (unsigned long) dst_key_alg(key))
490 ret = DST_R_INVALIDPRIVATEKEY;
491 goto fail;
494 READLINE(lex, opt, &token);
497 * Read the key data.
499 for (n = 0; n < MAXFIELDS; n++) {
500 int tag;
501 isc_region_t r;
502 do {
503 ret = isc_lex_gettoken(lex, opt, &token);
504 if (ret == ISC_R_EOF)
505 goto done;
506 if (ret != ISC_R_SUCCESS)
507 goto fail;
508 } while (token.type == isc_tokentype_eol);
510 if (token.type != isc_tokentype_string) {
511 ret = DST_R_INVALIDPRIVATEKEY;
512 goto fail;
515 if (strcmp(DST_AS_STR(token), "External:") == 0) {
516 external = ISC_TRUE;
517 goto next;
520 /* Numeric metadata */
521 tag = find_numericdata(DST_AS_STR(token));
522 if (tag >= 0) {
523 INSIST(tag < NUMERIC_NTAGS);
525 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
526 if (token.type != isc_tokentype_number) {
527 ret = DST_R_INVALIDPRIVATEKEY;
528 goto fail;
531 dst_key_setnum(key, tag, token.value.as_ulong);
532 goto next;
535 /* Timing metadata */
536 tag = find_timedata(DST_AS_STR(token));
537 if (tag >= 0) {
538 INSIST(tag < TIMING_NTAGS);
540 NEXTTOKEN(lex, opt, &token);
541 if (token.type != isc_tokentype_string) {
542 ret = DST_R_INVALIDPRIVATEKEY;
543 goto fail;
546 ret = dns_time32_fromtext(DST_AS_STR(token), &when);
547 if (ret != ISC_R_SUCCESS)
548 goto fail;
550 dst_key_settime(key, tag, when);
552 goto next;
555 /* Key data */
556 tag = find_value(DST_AS_STR(token), alg);
557 if (tag < 0 && minor > DST_MINOR_VERSION)
558 goto next;
559 else if (tag < 0) {
560 ret = DST_R_INVALIDPRIVATEKEY;
561 goto fail;
564 priv->elements[n].tag = tag;
566 data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE);
567 if (data == NULL)
568 goto fail;
570 isc_buffer_init(&b, data, MAXFIELDSIZE);
571 ret = isc_base64_tobuffer(lex, &b, -1);
572 if (ret != ISC_R_SUCCESS)
573 goto fail;
575 isc_buffer_usedregion(&b, &r);
576 priv->elements[n].length = r.length;
577 priv->elements[n].data = r.base;
578 priv->nelements++;
580 next:
581 READLINE(lex, opt, &token);
582 data = NULL;
585 done:
586 if (external && priv->nelements != 0) {
587 ret = DST_R_INVALIDPRIVATEKEY;
588 goto fail;
591 check = check_data(priv, alg, ISC_TRUE, external);
592 if (check < 0) {
593 ret = DST_R_INVALIDPRIVATEKEY;
594 goto fail;
595 } else if (check != ISC_R_SUCCESS) {
596 ret = check;
597 goto fail;
600 key->external = external;
602 return (ISC_R_SUCCESS);
604 fail:
605 dst__privstruct_free(priv, mctx);
606 if (data != NULL)
607 isc_mem_put(mctx, data, MAXFIELDSIZE);
609 return (ret);
612 isc_result_t
613 dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
614 const char *directory)
616 FILE *fp;
617 isc_result_t result;
618 char filename[ISC_DIR_NAMEMAX];
619 char buffer[MAXFIELDSIZE * 2];
620 isc_fsaccess_t access;
621 isc_stdtime_t when;
622 isc_uint32_t value;
623 isc_buffer_t b;
624 isc_region_t r;
625 int major, minor;
626 mode_t mode;
627 int i, ret;
629 REQUIRE(priv != NULL);
631 ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external);
632 if (ret < 0)
633 return (DST_R_INVALIDPRIVATEKEY);
634 else if (ret != ISC_R_SUCCESS)
635 return (ret);
637 isc_buffer_init(&b, filename, sizeof(filename));
638 result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b);
639 if (result != ISC_R_SUCCESS)
640 return (result);
642 result = isc_file_mode(filename, &mode);
643 if (result == ISC_R_SUCCESS && mode != 0600) {
644 /* File exists; warn that we are changing its permissions */
645 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
646 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
647 "Permissions on the file %s "
648 "have changed from 0%o to 0600 as "
649 "a result of this operation.",
650 filename, (unsigned int)mode);
653 if ((fp = fopen(filename, "w")) == NULL)
654 return (DST_R_WRITEERROR);
656 access = 0;
657 isc_fsaccess_add(ISC_FSACCESS_OWNER,
658 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
659 &access);
660 (void)isc_fsaccess_set(filename, access);
662 dst_key_getprivateformat(key, &major, &minor);
663 if (major == 0 && minor == 0) {
664 major = DST_MAJOR_VERSION;
665 minor = DST_MINOR_VERSION;
668 /* XXXDCL return value should be checked for full filesystem */
669 fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor);
671 fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key));
673 /* XXXVIX this switch statement is too sparse to gen a jump table. */
674 switch (dst_key_alg(key)) {
675 case DST_ALG_RSAMD5:
676 fprintf(fp, "(RSA)\n");
677 break;
678 case DST_ALG_DH:
679 fprintf(fp, "(DH)\n");
680 break;
681 case DST_ALG_DSA:
682 fprintf(fp, "(DSA)\n");
683 break;
684 case DST_ALG_RSASHA1:
685 fprintf(fp, "(RSASHA1)\n");
686 break;
687 case DST_ALG_NSEC3RSASHA1:
688 fprintf(fp, "(NSEC3RSASHA1)\n");
689 break;
690 case DST_ALG_NSEC3DSA:
691 fprintf(fp, "(NSEC3DSA)\n");
692 break;
693 case DST_ALG_RSASHA256:
694 fprintf(fp, "(RSASHA256)\n");
695 break;
696 case DST_ALG_RSASHA512:
697 fprintf(fp, "(RSASHA512)\n");
698 break;
699 case DST_ALG_ECCGOST:
700 fprintf(fp, "(ECC-GOST)\n");
701 break;
702 case DST_ALG_ECDSA256:
703 fprintf(fp, "(ECDSAP256SHA256)\n");
704 break;
705 case DST_ALG_ECDSA384:
706 fprintf(fp, "(ECDSAP384SHA384)\n");
707 break;
708 case DST_ALG_HMACMD5:
709 fprintf(fp, "(HMAC_MD5)\n");
710 break;
711 case DST_ALG_HMACSHA1:
712 fprintf(fp, "(HMAC_SHA1)\n");
713 break;
714 case DST_ALG_HMACSHA224:
715 fprintf(fp, "(HMAC_SHA224)\n");
716 break;
717 case DST_ALG_HMACSHA256:
718 fprintf(fp, "(HMAC_SHA256)\n");
719 break;
720 case DST_ALG_HMACSHA384:
721 fprintf(fp, "(HMAC_SHA384)\n");
722 break;
723 case DST_ALG_HMACSHA512:
724 fprintf(fp, "(HMAC_SHA512)\n");
725 break;
726 default:
727 fprintf(fp, "(?)\n");
728 break;
731 for (i = 0; i < priv->nelements; i++) {
732 const char *s;
734 s = find_tag(priv->elements[i].tag);
736 r.base = priv->elements[i].data;
737 r.length = priv->elements[i].length;
738 isc_buffer_init(&b, buffer, sizeof(buffer));
739 result = isc_base64_totext(&r, sizeof(buffer), "", &b);
740 if (result != ISC_R_SUCCESS) {
741 fclose(fp);
742 return (DST_R_INVALIDPRIVATEKEY);
744 isc_buffer_usedregion(&b, &r);
746 fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);
749 if (key->external)
750 fprintf(fp, "External:\n");
752 /* Add the metadata tags */
753 if (major > 1 || (major == 1 && minor >= 3)) {
754 for (i = 0; i < NUMERIC_NTAGS; i++) {
755 result = dst_key_getnum(key, i, &value);
756 if (result != ISC_R_SUCCESS)
757 continue;
758 fprintf(fp, "%s %u\n", numerictags[i], value);
760 for (i = 0; i < TIMING_NTAGS; i++) {
761 result = dst_key_gettime(key, i, &when);
762 if (result != ISC_R_SUCCESS)
763 continue;
765 isc_buffer_init(&b, buffer, sizeof(buffer));
766 result = dns_time32_totext(when, &b);
767 if (result != ISC_R_SUCCESS) {
768 fclose(fp);
769 return (DST_R_INVALIDPRIVATEKEY);
772 isc_buffer_usedregion(&b, &r);
774 fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
775 r.base);
779 fflush(fp);
780 result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
781 fclose(fp);
782 return (result);
785 /*! \file */