00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <config.h>
00038
00039 #include <isc/base64.h>
00040 #include <isc/dir.h>
00041 #include <isc/fsaccess.h>
00042 #include <isc/lex.h>
00043 #include <isc/mem.h>
00044 #include <isc/stdtime.h>
00045 #include <isc/string.h>
00046 #include <isc/util.h>
00047 #include <isc/file.h>
00048
00049 #include <dns/time.h>
00050 #include <dns/log.h>
00051
00052 #include "dst_internal.h"
00053 #include "dst_parse.h"
00054 #include "dst/result.h"
00055
00056 #define DST_AS_STR(t) ((t).value.as_textregion.base)
00057
00058 #define PRIVATE_KEY_STR "Private-key-format:"
00059 #define ALGORITHM_STR "Algorithm:"
00060
00061 #define TIMING_NTAGS (DST_MAX_TIMES + 1)
00062 static const char *timetags[TIMING_NTAGS] = {
00063 "Created:",
00064 "Publish:",
00065 "Activate:",
00066 "Revoke:",
00067 "Inactive:",
00068 "Delete:",
00069 "DSPublish:"
00070 };
00071
00072 #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
00073 static const char *numerictags[NUMERIC_NTAGS] = {
00074 "Predecessor:",
00075 "Successor:",
00076 "MaxTTL:",
00077 "RollPeriod:"
00078 };
00079
00080 struct parse_map {
00081 const int value;
00082 const char *tag;
00083 };
00084
00085 static struct parse_map map[] = {
00086 {TAG_RSA_MODULUS, "Modulus:"},
00087 {TAG_RSA_PUBLICEXPONENT, "PublicExponent:"},
00088 {TAG_RSA_PRIVATEEXPONENT, "PrivateExponent:"},
00089 {TAG_RSA_PRIME1, "Prime1:"},
00090 {TAG_RSA_PRIME2, "Prime2:"},
00091 {TAG_RSA_EXPONENT1, "Exponent1:"},
00092 {TAG_RSA_EXPONENT2, "Exponent2:"},
00093 {TAG_RSA_COEFFICIENT, "Coefficient:"},
00094 {TAG_RSA_ENGINE, "Engine:" },
00095 {TAG_RSA_LABEL, "Label:" },
00096
00097 {TAG_DH_PRIME, "Prime(p):"},
00098 {TAG_DH_GENERATOR, "Generator(g):"},
00099 {TAG_DH_PRIVATE, "Private_value(x):"},
00100 {TAG_DH_PUBLIC, "Public_value(y):"},
00101
00102 {TAG_DSA_PRIME, "Prime(p):"},
00103 {TAG_DSA_SUBPRIME, "Subprime(q):"},
00104 {TAG_DSA_BASE, "Base(g):"},
00105 {TAG_DSA_PRIVATE, "Private_value(x):"},
00106 {TAG_DSA_PUBLIC, "Public_value(y):"},
00107
00108 {TAG_GOST_PRIVASN1, "GostAsn1:"},
00109 {TAG_GOST_PRIVRAW, "PrivateKey:"},
00110
00111 {TAG_ECDSA_PRIVATEKEY, "PrivateKey:"},
00112 {TAG_ECDSA_ENGINE, "Engine:" },
00113 {TAG_ECDSA_LABEL, "Label:" },
00114
00115 {TAG_HMACMD5_KEY, "Key:"},
00116 {TAG_HMACMD5_BITS, "Bits:"},
00117
00118 {TAG_HMACSHA1_KEY, "Key:"},
00119 {TAG_HMACSHA1_BITS, "Bits:"},
00120
00121 {TAG_HMACSHA224_KEY, "Key:"},
00122 {TAG_HMACSHA224_BITS, "Bits:"},
00123
00124 {TAG_HMACSHA256_KEY, "Key:"},
00125 {TAG_HMACSHA256_BITS, "Bits:"},
00126
00127 {TAG_HMACSHA384_KEY, "Key:"},
00128 {TAG_HMACSHA384_BITS, "Bits:"},
00129
00130 {TAG_HMACSHA512_KEY, "Key:"},
00131 {TAG_HMACSHA512_BITS, "Bits:"},
00132
00133 {0, NULL}
00134 };
00135
00136 static int
00137 find_value(const char *s, const unsigned int alg) {
00138 int i;
00139
00140 for (i = 0; map[i].tag != NULL; i++) {
00141 if (strcasecmp(s, map[i].tag) == 0 &&
00142 (TAG_ALG(map[i].value) == alg))
00143 return (map[i].value);
00144 }
00145 return (-1);
00146 }
00147
00148 static const char *
00149 find_tag(const int value) {
00150 int i;
00151
00152 for (i = 0; ; i++) {
00153 if (map[i].tag == NULL)
00154 return (NULL);
00155 else if (value == map[i].value)
00156 return (map[i].tag);
00157 }
00158 }
00159
00160 static int
00161 find_metadata(const char *s, const char *tags[], int ntags) {
00162 int i;
00163
00164 for (i = 0; i < ntags; i++) {
00165 if (strcasecmp(s, tags[i]) == 0)
00166 return (i);
00167 }
00168
00169 return (-1);
00170 }
00171
00172 static int
00173 find_timedata(const char *s) {
00174 return (find_metadata(s, timetags, TIMING_NTAGS));
00175 }
00176
00177 static int
00178 find_numericdata(const char *s) {
00179 return (find_metadata(s, numerictags, NUMERIC_NTAGS));
00180 }
00181
00182 static int
00183 check_rsa(const dst_private_t *priv, isc_boolean_t external) {
00184 int i, j;
00185 isc_boolean_t have[RSA_NTAGS];
00186 isc_boolean_t ok;
00187 unsigned int mask;
00188
00189 if (external)
00190 return ((priv->nelements == 0) ? 0 : -1);
00191
00192 for (i = 0; i < RSA_NTAGS; i++)
00193 have[i] = ISC_FALSE;
00194
00195 for (j = 0; j < priv->nelements; j++) {
00196 for (i = 0; i < RSA_NTAGS; i++)
00197 if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i))
00198 break;
00199 if (i == RSA_NTAGS)
00200 return (-1);
00201 have[i] = ISC_TRUE;
00202 }
00203
00204 mask = ~0;
00205 mask <<= sizeof(mask) * 8 - TAG_SHIFT;
00206 mask >>= sizeof(mask) * 8 - TAG_SHIFT;
00207
00208 if (have[TAG_RSA_ENGINE & mask])
00209 ok = have[TAG_RSA_MODULUS & mask] &&
00210 have[TAG_RSA_PUBLICEXPONENT & mask] &&
00211 have[TAG_RSA_LABEL & mask];
00212 else
00213 ok = have[TAG_RSA_MODULUS & mask] &&
00214 have[TAG_RSA_PUBLICEXPONENT & mask] &&
00215 have[TAG_RSA_PRIVATEEXPONENT & mask] &&
00216 have[TAG_RSA_PRIME1 & mask] &&
00217 have[TAG_RSA_PRIME2 & mask] &&
00218 have[TAG_RSA_EXPONENT1 & mask] &&
00219 have[TAG_RSA_EXPONENT2 & mask] &&
00220 have[TAG_RSA_COEFFICIENT & mask];
00221 return (ok ? 0 : -1 );
00222 }
00223
00224 static int
00225 check_dh(const dst_private_t *priv) {
00226 int i, j;
00227 if (priv->nelements != DH_NTAGS)
00228 return (-1);
00229 for (i = 0; i < DH_NTAGS; i++) {
00230 for (j = 0; j < priv->nelements; j++)
00231 if (priv->elements[j].tag == TAG(DST_ALG_DH, i))
00232 break;
00233 if (j == priv->nelements)
00234 return (-1);
00235 }
00236 return (0);
00237 }
00238
00239 static int
00240 check_dsa(const dst_private_t *priv, isc_boolean_t external) {
00241 int i, j;
00242
00243 if (external)
00244 return ((priv->nelements == 0)? 0 : -1);
00245
00246 if (priv->nelements != DSA_NTAGS)
00247 return (-1);
00248
00249 for (i = 0; i < DSA_NTAGS; i++) {
00250 for (j = 0; j < priv->nelements; j++)
00251 if (priv->elements[j].tag == TAG(DST_ALG_DSA, i))
00252 break;
00253 if (j == priv->nelements)
00254 return (-1);
00255 }
00256 return (0);
00257 }
00258
00259 static int
00260 check_gost(const dst_private_t *priv, isc_boolean_t external) {
00261
00262 if (external)
00263 return ((priv->nelements == 0)? 0 : -1);
00264
00265 if (priv->nelements != GOST_NTAGS)
00266 return (-1);
00267 if ((priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) &&
00268 (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 1)))
00269 return (-1);
00270 return (0);
00271 }
00272
00273 static int
00274 check_ecdsa(const dst_private_t *priv, isc_boolean_t external) {
00275 int i, j;
00276 isc_boolean_t have[ECDSA_NTAGS];
00277 isc_boolean_t ok;
00278 unsigned int mask;
00279
00280 if (external)
00281 return ((priv->nelements == 0) ? 0 : -1);
00282
00283 for (i = 0; i < ECDSA_NTAGS; i++)
00284 have[i] = ISC_FALSE;
00285 for (j = 0; j < priv->nelements; j++) {
00286 for (i = 0; i < ECDSA_NTAGS; i++)
00287 if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i))
00288 break;
00289 if (i == ECDSA_NTAGS)
00290 return (-1);
00291 have[i] = ISC_TRUE;
00292 }
00293
00294 mask = ~0;
00295 mask <<= sizeof(mask) * 8 - TAG_SHIFT;
00296 mask >>= sizeof(mask) * 8 - TAG_SHIFT;
00297
00298 if (have[TAG_ECDSA_ENGINE & mask])
00299 ok = have[TAG_ECDSA_LABEL & mask];
00300 else
00301 ok = have[TAG_ECDSA_PRIVATEKEY & mask];
00302 return (ok ? 0 : -1 );
00303 }
00304
00305 static int
00306 check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) {
00307 int i, j;
00308
00309 if (priv->nelements != HMACMD5_NTAGS) {
00310
00311
00312
00313
00314 if (old && priv->nelements == OLD_HMACMD5_NTAGS &&
00315 priv->elements[0].tag == TAG_HMACMD5_KEY)
00316 return (0);
00317 return (-1);
00318 }
00319
00320
00321
00322 for (i = 0; i < HMACMD5_NTAGS; i++) {
00323 for (j = 0; j < priv->nelements; j++)
00324 if (priv->elements[j].tag == TAG(DST_ALG_HMACMD5, i))
00325 break;
00326 if (j == priv->nelements)
00327 return (-1);
00328 }
00329 return (0);
00330 }
00331
00332 static int
00333 check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
00334 unsigned int alg)
00335 {
00336 unsigned int i, j;
00337 if (priv->nelements != ntags)
00338 return (-1);
00339 for (i = 0; i < ntags; i++) {
00340 for (j = 0; j < priv->nelements; j++)
00341 if (priv->elements[j].tag == TAG(alg, i))
00342 break;
00343 if (j == priv->nelements)
00344 return (-1);
00345 }
00346 return (0);
00347 }
00348
00349 static int
00350 check_data(const dst_private_t *priv, const unsigned int alg,
00351 isc_boolean_t old, isc_boolean_t external)
00352 {
00353
00354 switch (alg) {
00355 case DST_ALG_RSAMD5:
00356 case DST_ALG_RSASHA1:
00357 case DST_ALG_NSEC3RSASHA1:
00358 case DST_ALG_RSASHA256:
00359 case DST_ALG_RSASHA512:
00360 return (check_rsa(priv, external));
00361 case DST_ALG_DH:
00362 return (check_dh(priv));
00363 case DST_ALG_DSA:
00364 case DST_ALG_NSEC3DSA:
00365 return (check_dsa(priv, external));
00366 case DST_ALG_ECCGOST:
00367 return (check_gost(priv, external));
00368 case DST_ALG_ECDSA256:
00369 case DST_ALG_ECDSA384:
00370 return (check_ecdsa(priv, external));
00371 case DST_ALG_HMACMD5:
00372 return (check_hmac_md5(priv, old));
00373 case DST_ALG_HMACSHA1:
00374 return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg));
00375 case DST_ALG_HMACSHA224:
00376 return (check_hmac_sha(priv, HMACSHA224_NTAGS, alg));
00377 case DST_ALG_HMACSHA256:
00378 return (check_hmac_sha(priv, HMACSHA256_NTAGS, alg));
00379 case DST_ALG_HMACSHA384:
00380 return (check_hmac_sha(priv, HMACSHA384_NTAGS, alg));
00381 case DST_ALG_HMACSHA512:
00382 return (check_hmac_sha(priv, HMACSHA512_NTAGS, alg));
00383 default:
00384 return (DST_R_UNSUPPORTEDALG);
00385 }
00386 }
00387
00388 void
00389 dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) {
00390 int i;
00391
00392 if (priv == NULL)
00393 return;
00394 for (i = 0; i < priv->nelements; i++) {
00395 if (priv->elements[i].data == NULL)
00396 continue;
00397 memset(priv->elements[i].data, 0, MAXFIELDSIZE);
00398 isc_mem_put(mctx, priv->elements[i].data, MAXFIELDSIZE);
00399 }
00400 priv->nelements = 0;
00401 }
00402
00403 isc_result_t
00404 dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
00405 isc_mem_t *mctx, dst_private_t *priv)
00406 {
00407 int n = 0, major, minor, check;
00408 isc_buffer_t b;
00409 isc_token_t token;
00410 unsigned char *data = NULL;
00411 unsigned int opt = ISC_LEXOPT_EOL;
00412 isc_stdtime_t when;
00413 isc_result_t ret;
00414 isc_boolean_t external = ISC_FALSE;
00415
00416 REQUIRE(priv != NULL);
00417
00418 priv->nelements = 0;
00419 memset(priv->elements, 0, sizeof(priv->elements));
00420
00421 #define NEXTTOKEN(lex, opt, token) \
00422 do { \
00423 ret = isc_lex_gettoken(lex, opt, token); \
00424 if (ret != ISC_R_SUCCESS) \
00425 goto fail; \
00426 } while (0)
00427
00428 #define READLINE(lex, opt, token) \
00429 do { \
00430 ret = isc_lex_gettoken(lex, opt, token); \
00431 if (ret == ISC_R_EOF) \
00432 break; \
00433 else if (ret != ISC_R_SUCCESS) \
00434 goto fail; \
00435 } while ((*token).type != isc_tokentype_eol)
00436
00437
00438
00439
00440 NEXTTOKEN(lex, opt, &token);
00441 if (token.type != isc_tokentype_string ||
00442 strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0)
00443 {
00444 ret = DST_R_INVALIDPRIVATEKEY;
00445 goto fail;
00446 }
00447
00448 NEXTTOKEN(lex, opt, &token);
00449 if (token.type != isc_tokentype_string ||
00450 (DST_AS_STR(token))[0] != 'v')
00451 {
00452 ret = DST_R_INVALIDPRIVATEKEY;
00453 goto fail;
00454 }
00455 if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2)
00456 {
00457 ret = DST_R_INVALIDPRIVATEKEY;
00458 goto fail;
00459 }
00460
00461 if (major > DST_MAJOR_VERSION) {
00462 ret = DST_R_INVALIDPRIVATEKEY;
00463 goto fail;
00464 }
00465
00466
00467
00468
00469 dst_key_setprivateformat(key, major, minor);
00470
00471 READLINE(lex, opt, &token);
00472
00473
00474
00475
00476 NEXTTOKEN(lex, opt, &token);
00477 if (token.type != isc_tokentype_string ||
00478 strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0)
00479 {
00480 ret = DST_R_INVALIDPRIVATEKEY;
00481 goto fail;
00482 }
00483
00484 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
00485 if (token.type != isc_tokentype_number ||
00486 token.value.as_ulong != (unsigned long) dst_key_alg(key))
00487 {
00488 ret = DST_R_INVALIDPRIVATEKEY;
00489 goto fail;
00490 }
00491
00492 READLINE(lex, opt, &token);
00493
00494
00495
00496
00497 for (n = 0; n < MAXFIELDS; n++) {
00498 int tag;
00499 isc_region_t r;
00500 do {
00501 ret = isc_lex_gettoken(lex, opt, &token);
00502 if (ret == ISC_R_EOF)
00503 goto done;
00504 if (ret != ISC_R_SUCCESS)
00505 goto fail;
00506 } while (token.type == isc_tokentype_eol);
00507
00508 if (token.type != isc_tokentype_string) {
00509 ret = DST_R_INVALIDPRIVATEKEY;
00510 goto fail;
00511 }
00512
00513 if (strcmp(DST_AS_STR(token), "External:") == 0) {
00514 external = ISC_TRUE;
00515 goto next;
00516 }
00517
00518
00519 tag = find_numericdata(DST_AS_STR(token));
00520 if (tag >= 0) {
00521 INSIST(tag < NUMERIC_NTAGS);
00522
00523 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
00524 if (token.type != isc_tokentype_number) {
00525 ret = DST_R_INVALIDPRIVATEKEY;
00526 goto fail;
00527 }
00528
00529 dst_key_setnum(key, tag, token.value.as_ulong);
00530 goto next;
00531 }
00532
00533
00534 tag = find_timedata(DST_AS_STR(token));
00535 if (tag >= 0) {
00536 INSIST(tag < TIMING_NTAGS);
00537
00538 NEXTTOKEN(lex, opt, &token);
00539 if (token.type != isc_tokentype_string) {
00540 ret = DST_R_INVALIDPRIVATEKEY;
00541 goto fail;
00542 }
00543
00544 ret = dns_time32_fromtext(DST_AS_STR(token), &when);
00545 if (ret != ISC_R_SUCCESS)
00546 goto fail;
00547
00548 dst_key_settime(key, tag, when);
00549
00550 goto next;
00551 }
00552
00553
00554 tag = find_value(DST_AS_STR(token), alg);
00555 if (tag < 0 && minor > DST_MINOR_VERSION)
00556 goto next;
00557 else if (tag < 0) {
00558 ret = DST_R_INVALIDPRIVATEKEY;
00559 goto fail;
00560 }
00561
00562 priv->elements[n].tag = tag;
00563
00564 data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE);
00565 if (data == NULL)
00566 goto fail;
00567
00568 isc_buffer_init(&b, data, MAXFIELDSIZE);
00569 ret = isc_base64_tobuffer(lex, &b, -1);
00570 if (ret != ISC_R_SUCCESS)
00571 goto fail;
00572
00573 isc_buffer_usedregion(&b, &r);
00574 priv->elements[n].length = r.length;
00575 priv->elements[n].data = r.base;
00576 priv->nelements++;
00577
00578 next:
00579 READLINE(lex, opt, &token);
00580 data = NULL;
00581 }
00582
00583 done:
00584 if (external && priv->nelements != 0) {
00585 ret = DST_R_INVALIDPRIVATEKEY;
00586 goto fail;
00587 }
00588
00589 check = check_data(priv, alg, ISC_TRUE, external);
00590 if (check < 0) {
00591 ret = DST_R_INVALIDPRIVATEKEY;
00592 goto fail;
00593 } else if (check != ISC_R_SUCCESS) {
00594 ret = check;
00595 goto fail;
00596 }
00597
00598 key->external = external;
00599
00600 return (ISC_R_SUCCESS);
00601
00602 fail:
00603 dst__privstruct_free(priv, mctx);
00604 if (data != NULL)
00605 isc_mem_put(mctx, data, MAXFIELDSIZE);
00606
00607 return (ret);
00608 }
00609
00610 isc_result_t
00611 dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
00612 const char *directory)
00613 {
00614 FILE *fp;
00615 isc_result_t result;
00616 char filename[ISC_DIR_NAMEMAX];
00617 char buffer[MAXFIELDSIZE * 2];
00618 isc_fsaccess_t access;
00619 isc_stdtime_t when;
00620 isc_uint32_t value;
00621 isc_buffer_t b;
00622 isc_region_t r;
00623 int major, minor;
00624 mode_t mode;
00625 int i, ret;
00626
00627 REQUIRE(priv != NULL);
00628
00629 ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external);
00630 if (ret < 0)
00631 return (DST_R_INVALIDPRIVATEKEY);
00632 else if (ret != ISC_R_SUCCESS)
00633 return (ret);
00634
00635 isc_buffer_init(&b, filename, sizeof(filename));
00636 result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b);
00637 if (result != ISC_R_SUCCESS)
00638 return (result);
00639
00640 result = isc_file_mode(filename, &mode);
00641 if (result == ISC_R_SUCCESS && mode != 0600) {
00642
00643 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00644 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
00645 "Permissions on the file %s "
00646 "have changed from 0%o to 0600 as "
00647 "a result of this operation.",
00648 filename, (unsigned int)mode);
00649 }
00650
00651 if ((fp = fopen(filename, "w")) == NULL)
00652 return (DST_R_WRITEERROR);
00653
00654 access = 0;
00655 isc_fsaccess_add(ISC_FSACCESS_OWNER,
00656 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
00657 &access);
00658 (void)isc_fsaccess_set(filename, access);
00659
00660 dst_key_getprivateformat(key, &major, &minor);
00661 if (major == 0 && minor == 0) {
00662 major = DST_MAJOR_VERSION;
00663 minor = DST_MINOR_VERSION;
00664 }
00665
00666
00667 fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor);
00668
00669 fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key));
00670
00671
00672 switch (dst_key_alg(key)) {
00673 case DST_ALG_RSAMD5:
00674 fprintf(fp, "(RSA)\n");
00675 break;
00676 case DST_ALG_DH:
00677 fprintf(fp, "(DH)\n");
00678 break;
00679 case DST_ALG_DSA:
00680 fprintf(fp, "(DSA)\n");
00681 break;
00682 case DST_ALG_RSASHA1:
00683 fprintf(fp, "(RSASHA1)\n");
00684 break;
00685 case DST_ALG_NSEC3RSASHA1:
00686 fprintf(fp, "(NSEC3RSASHA1)\n");
00687 break;
00688 case DST_ALG_NSEC3DSA:
00689 fprintf(fp, "(NSEC3DSA)\n");
00690 break;
00691 case DST_ALG_RSASHA256:
00692 fprintf(fp, "(RSASHA256)\n");
00693 break;
00694 case DST_ALG_RSASHA512:
00695 fprintf(fp, "(RSASHA512)\n");
00696 break;
00697 case DST_ALG_ECCGOST:
00698 fprintf(fp, "(ECC-GOST)\n");
00699 break;
00700 case DST_ALG_ECDSA256:
00701 fprintf(fp, "(ECDSAP256SHA256)\n");
00702 break;
00703 case DST_ALG_ECDSA384:
00704 fprintf(fp, "(ECDSAP384SHA384)\n");
00705 break;
00706 case DST_ALG_HMACMD5:
00707 fprintf(fp, "(HMAC_MD5)\n");
00708 break;
00709 case DST_ALG_HMACSHA1:
00710 fprintf(fp, "(HMAC_SHA1)\n");
00711 break;
00712 case DST_ALG_HMACSHA224:
00713 fprintf(fp, "(HMAC_SHA224)\n");
00714 break;
00715 case DST_ALG_HMACSHA256:
00716 fprintf(fp, "(HMAC_SHA256)\n");
00717 break;
00718 case DST_ALG_HMACSHA384:
00719 fprintf(fp, "(HMAC_SHA384)\n");
00720 break;
00721 case DST_ALG_HMACSHA512:
00722 fprintf(fp, "(HMAC_SHA512)\n");
00723 break;
00724 default:
00725 fprintf(fp, "(?)\n");
00726 break;
00727 }
00728
00729 for (i = 0; i < priv->nelements; i++) {
00730 const char *s;
00731
00732 s = find_tag(priv->elements[i].tag);
00733
00734 r.base = priv->elements[i].data;
00735 r.length = priv->elements[i].length;
00736 isc_buffer_init(&b, buffer, sizeof(buffer));
00737 result = isc_base64_totext(&r, sizeof(buffer), "", &b);
00738 if (result != ISC_R_SUCCESS) {
00739 fclose(fp);
00740 return (DST_R_INVALIDPRIVATEKEY);
00741 }
00742 isc_buffer_usedregion(&b, &r);
00743
00744 fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);
00745 }
00746
00747 if (key->external)
00748 fprintf(fp, "External:\n");
00749
00750
00751 if (major > 1 || (major == 1 && minor >= 3)) {
00752 for (i = 0; i < NUMERIC_NTAGS; i++) {
00753 result = dst_key_getnum(key, i, &value);
00754 if (result != ISC_R_SUCCESS)
00755 continue;
00756 fprintf(fp, "%s %u\n", numerictags[i], value);
00757 }
00758 for (i = 0; i < TIMING_NTAGS; i++) {
00759 result = dst_key_gettime(key, i, &when);
00760 if (result != ISC_R_SUCCESS)
00761 continue;
00762
00763 isc_buffer_init(&b, buffer, sizeof(buffer));
00764 result = dns_time32_totext(when, &b);
00765 if (result != ISC_R_SUCCESS) {
00766 fclose(fp);
00767 return (DST_R_INVALIDPRIVATEKEY);
00768 }
00769
00770 isc_buffer_usedregion(&b, &r);
00771
00772 fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
00773 r.base);
00774 }
00775 }
00776
00777 fflush(fp);
00778 result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
00779 fclose(fp);
00780 return (result);
00781 }
00782
00783