ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
{
	ldns_status status = LDNS_STATUS_OK;
	unsigned char  *bignum;
#ifdef HAVE_SSL
#  ifndef S_SPLINT_S
	uint16_t i;
#  endif
	/* not used when ssl is not defined */
	/*@unused@*/
	ldns_rdf *b64_bignum = NULL;

	RSA *rsa;
	DSA *dsa;
#endif /* HAVE_SSL */

	if (!k) {
		return LDNS_STATUS_ERR;
	}

	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
	if (!bignum) {
		return LDNS_STATUS_ERR;
	}

	if (ldns_buffer_status_ok(output)) {
#ifdef HAVE_SSL
		switch(ldns_key_algorithm(k)) {
			case LDNS_SIGN_RSASHA1:
			case LDNS_SIGN_RSASHA1_NSEC3:
			case LDNS_SIGN_RSASHA256:
			case LDNS_SIGN_RSASHA512:
			case LDNS_SIGN_RSAMD5:
				/* copied by looking at dnssec-keygen output */
				/* header */
				rsa = ldns_key_rsa_key(k);

				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
				switch(ldns_key_algorithm(k)) {
				case LDNS_SIGN_RSAMD5:
					ldns_buffer_printf(output,
								    "Algorithm: %u (RSA)\n",
								    LDNS_RSAMD5);
					break;
				case LDNS_SIGN_RSASHA1:
					ldns_buffer_printf(output,
								    "Algorithm: %u (RSASHA1)\n",
								    LDNS_RSASHA1);
					break;
				case LDNS_SIGN_RSASHA1_NSEC3:
					ldns_buffer_printf(output,
								    "Algorithm: %u (RSASHA1_NSEC3)\n",
								    LDNS_RSASHA1_NSEC3);
					break;
#ifdef USE_SHA2
				case LDNS_SIGN_RSASHA256:
					ldns_buffer_printf(output,
								    "Algorithm: %u (RSASHA256)\n",
								    LDNS_RSASHA256);
					break;
				case LDNS_SIGN_RSASHA512:
					ldns_buffer_printf(output,
								    "Algorithm: %u (RSASHA512)\n",
								    LDNS_RSASHA512);
					break;
#endif
				default:
					fprintf(stderr, "Warning: unknown signature ");
					fprintf(stderr,
						   "algorithm type %u\n",
						   ldns_key_algorithm(k));
					ldns_buffer_printf(output,
								    "Algorithm: %u (Unknown)\n",
								    ldns_key_algorithm(k));
					break;
				}

				/* print to buf, convert to bin, convert to b64,
				 * print to buf */
				ldns_buffer_printf(output, "Modulus: ");
#ifndef S_SPLINT_S
				i = (uint16_t)BN_bn2bin(rsa->n, bignum);
				if (i > LDNS_MAX_KEYLEN) {
					goto error;
				}
				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
					ldns_rdf_deep_free(b64_bignum);
					goto error;
				}
				ldns_rdf_deep_free(b64_bignum);
				ldns_buffer_printf(output, "\n");
				ldns_buffer_printf(output, "PublicExponent: ");
				i = (uint16_t)BN_bn2bin(rsa->e, bignum);
				if (i > LDNS_MAX_KEYLEN) {
					goto error;
				}
				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
					ldns_rdf_deep_free(b64_bignum);
					goto error;
				}
				ldns_rdf_deep_free(b64_bignum);
				ldns_buffer_printf(output, "\n");

				ldns_buffer_printf(output, "PrivateExponent: ");
				if (rsa->d) {
					i = (uint16_t)BN_bn2bin(rsa->d, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}

				ldns_buffer_printf(output, "Prime1: ");
				if (rsa->p) {
					i = (uint16_t)BN_bn2bin(rsa->p, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}

				ldns_buffer_printf(output, "Prime2: ");
				if (rsa->q) {
					i = (uint16_t)BN_bn2bin(rsa->q, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}

				ldns_buffer_printf(output, "Exponent1: ");
				if (rsa->dmp1) {
					i = (uint16_t)BN_bn2bin(rsa->dmp1, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}

				ldns_buffer_printf(output, "Exponent2: ");
				if (rsa->dmq1) {
					i = (uint16_t)BN_bn2bin(rsa->dmq1, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}

				ldns_buffer_printf(output, "Coefficient: ");
				if (rsa->iqmp) {
					i = (uint16_t)BN_bn2bin(rsa->iqmp, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					ldns_buffer_printf(output, "(Not available)\n");
				}
#endif /* splint */

				RSA_free(rsa);
				break;
			case LDNS_SIGN_DSA:
			case LDNS_SIGN_DSA_NSEC3:
				dsa = ldns_key_dsa_key(k);

				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
				}

				/* print to buf, convert to bin, convert to b64,
				 * print to buf */
				ldns_buffer_printf(output, "Prime(p): ");
#ifndef S_SPLINT_S
				if (dsa->p) {
					i = (uint16_t)BN_bn2bin(dsa->p, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					printf("(Not available)\n");
				}

				ldns_buffer_printf(output, "Subprime(q): ");
				if (dsa->q) {
					i = (uint16_t)BN_bn2bin(dsa->q, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					printf("(Not available)\n");
				}

				ldns_buffer_printf(output, "Base(g): ");
				if (dsa->g) {
					i = (uint16_t)BN_bn2bin(dsa->g, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					printf("(Not available)\n");
				}

				ldns_buffer_printf(output, "Private_value(x): ");
				if (dsa->priv_key) {
					i = (uint16_t)BN_bn2bin(dsa->priv_key, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					printf("(Not available)\n");
				}

				ldns_buffer_printf(output, "Public_value(y): ");
				if (dsa->pub_key) {
					i = (uint16_t)BN_bn2bin(dsa->pub_key, bignum);
					if (i > LDNS_MAX_KEYLEN) {
						goto error;
					}
					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
						goto error;
					}
					ldns_rdf_deep_free(b64_bignum);
					ldns_buffer_printf(output, "\n");
				} else {
					printf("(Not available)\n");
				}
#endif /* splint */
				break;
			case LDNS_SIGN_ECC_GOST:
				/* no format defined, use blob */
#if defined(HAVE_SSL) && defined(USE_GOST)
				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
				status = ldns_gost_key2buffer_str(output, 
#ifndef S_SPLINT_S
					k->_key.key
#else
					NULL
#endif
				);
#else
				goto error;
#endif /* GOST */
				break;
			case LDNS_SIGN_ECDSAP256SHA256:
			case LDNS_SIGN_ECDSAP384SHA384:
#ifdef USE_ECDSA
                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
#ifndef S_SPLINT_S
				ldns_buffer_printf(output, ")\n");
                                if(k->_key.key) {
                                        EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
                                        const BIGNUM* b = EC_KEY_get0_private_key(ec);
                                        ldns_buffer_printf(output, "PrivateKey: ");
                                        i = (uint16_t)BN_bn2bin(b, bignum);
                                        if (i > LDNS_MAX_KEYLEN) {
                                                goto error;
                                        }
                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
						ldns_rdf_deep_free(b64_bignum);
                                                goto error;
                                        }
                                        ldns_rdf_deep_free(b64_bignum);
				        ldns_buffer_printf(output, "\n");
                                        /* down reference count in EC_KEY
                                         * its still assigned to the PKEY */
                                        EC_KEY_free(ec);
                                }
#endif /* splint */
#else
				goto error;
#endif /* ECDSA */
                                break;
			case LDNS_SIGN_HMACMD5:
				/* there's not much of a format defined for TSIG */
				/* It's just a binary blob, Same for all algorithms */
                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
                ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
				status = ldns_hmac_key2buffer_str(output, k);
				break;
			case LDNS_SIGN_HMACSHA1:
		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
				status = ldns_hmac_key2buffer_str(output, k);
				break;
			case LDNS_SIGN_HMACSHA256:
		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
				status = ldns_hmac_key2buffer_str(output, k);
				break;
		}
#endif /* HAVE_SSL */
	} else {
		LDNS_FREE(bignum);
		return ldns_buffer_status(output);
	}
	LDNS_FREE(bignum);
	return status;

#ifdef HAVE_SSL
	/* compiles warn the label isn't used */
error:
	LDNS_FREE(bignum);
	return LDNS_STATUS_ERR;
#endif /* HAVE_SSL */

}