dst_api.c revision cffe96e26744abcf33494837b234219046a631d8
/*
* Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2003 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Principal Author: Brian Wellington
* $Id: dst_api.c,v 1.12 2008/03/31 05:00:30 marka Exp $
*/
/*! \file */
#include <config.h>
#include <stdlib.h>
#include <isc/fsaccess.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
#include <dns/rdataclass.h>
#include "dst_internal.h"
static unsigned int dst_entropy_flags = 0;
/*
* Static functions.
*/
unsigned int alg,
unsigned int flags,
unsigned int protocol,
unsigned int bits,
const char *directory);
unsigned int alg,
unsigned int type,
const char *directory,
isc_buffer_t *out);
unsigned int alg,
unsigned int flags,
unsigned int protocol,
#define RETERR(x) \
do { \
result = (x); \
if (result != ISC_R_SUCCESS) \
goto out; \
} while (0)
do { \
isc_result_t _r; \
if (_r != ISC_R_SUCCESS) \
return (_r); \
} while (0); \
static void *
if (size == 0U)
size = 1;
}
static void
}
#ifdef OPENSSL
/*
* When using --with-openssl, there seems to be no good way of not
* leaking memory due to the openssl error handling mechanism.
* Avoid assertions by using a local memory context and not checking
* for leaks on exit. Note: as there are leaks we cannot use
* ISC_MEMFLAG_INTERNAL as it will free up memory still being used
* by libcrypto.
*/
NULL, &dst__memory_pool, 0);
if (result != ISC_R_SUCCESS)
return (result);
#else
#endif
#ifdef OPENSSL
#ifdef HAVE_OPENSSL_DSA
#endif
#endif /* OPENSSL */
#ifdef GSSAPI
#endif
return (ISC_R_SUCCESS);
out:
return (result);
}
void
dst_lib_destroy(void) {
int i;
for (i = 0; i < DST_MAX_ALGS; i++)
dst_t_func[i]->cleanup();
#ifdef OPENSSL
#endif
if (dst__memory_pool != NULL)
if (dst_entropy_pool != NULL)
}
dst_algorithm_supported(unsigned int alg) {
return (ISC_FALSE);
return (ISC_TRUE);
}
return (DST_R_UNSUPPORTEDALG);
return (DST_R_NULLKEY);
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}
void
}
}
return (DST_R_NULLKEY);
return (DST_R_NOTPRIVATEKEY);
return (DST_R_NOTPRIVATEKEY);
}
return (DST_R_NULLKEY);
return (DST_R_NOTPUBLICKEY);
}
{
return (DST_R_NULLKEY);
return (DST_R_KEYCANNOTCOMPUTESECRET);
return (DST_R_NOTPRIVATEKEY);
}
return (DST_R_UNSUPPORTEDALG);
if (type & DST_TYPE_PUBLIC) {
if (ret != ISC_R_SUCCESS)
return (ret);
}
if ((type & DST_TYPE_PRIVATE) &&
else
return (ISC_R_SUCCESS);
}
{
char filename[ISC_DIR_NAMEMAX];
isc_buffer_t b;
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS) {
dst_key_free(&key);
return (result);
}
dst_key_free(&key);
return (DST_R_INVALIDPRIVATEKEY);
}
return (ISC_R_SUCCESS);
}
{
char *newfilename = NULL;
int newfilenamelen = 0;
if (newfilename == NULL)
return (ISC_R_NOMEMORY);
newfilename = NULL;
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_NOMEMORY);
if (newfilename == NULL)
return (ISC_R_SUCCESS);
out:
if (newfilename != NULL)
dst_key_free(&key);
return (result);
}
return (DST_R_UNSUPPORTEDALG);
return (ISC_R_NOSPACE);
return (ISC_R_NOSPACE);
& 0xffff));
}
return (ISC_R_SUCCESS);
}
{
isc_region_t r;
return (DST_R_INVALIDPUBLICKEY);
if (flags & DNS_KEYFLAG_EXTENDED) {
return (DST_R_INVALIDPUBLICKEY);
}
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
{
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS) {
dst_key_free(&key);
return (result);
}
return (ISC_R_SUCCESS);
}
return (DST_R_UNSUPPORTEDALG);
}
out:
return (result);
}
{
}
{
0, dns_rdataclass_in, mctx);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
{
return (ISC_R_NOMEMORY);
if (bits == 0) { /*%< NULL KEY */
return (ISC_R_SUCCESS);
}
dst_key_free(&key);
return (DST_R_UNSUPPORTEDALG);
}
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
}
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
}
return (ISC_R_SUCCESS);
}
return (ISC_TRUE);
return (ISC_FALSE);
return (ISC_TRUE);
else
return (ISC_FALSE);
}
return (ISC_TRUE);
return (ISC_FALSE);
return (ISC_TRUE);
else
return (ISC_FALSE);
}
void
}
}
}
type == 0);
}
/* XXXVIX this switch statement is too sparse to gen a jump table. */
case DST_ALG_RSAMD5:
case DST_ALG_RSASHA1:
break;
case DST_ALG_DSA:
*n = DNS_SIG_DSASIGSIZE;
break;
case DST_ALG_HMACMD5:
*n = 16;
break;
case DST_ALG_HMACSHA1:
*n = ISC_SHA1_DIGESTLENGTH;
break;
case DST_ALG_HMACSHA224:
*n = ISC_SHA224_DIGESTLENGTH;
break;
case DST_ALG_HMACSHA256:
*n = ISC_SHA256_DIGESTLENGTH;
break;
case DST_ALG_HMACSHA384:
*n = ISC_SHA384_DIGESTLENGTH;
break;
case DST_ALG_HMACSHA512:
*n = ISC_SHA512_DIGESTLENGTH;
break;
case DST_ALG_GSSAPI:
*n = 128; /*%< XXX */
break;
case DST_ALG_DH:
default:
return (DST_R_UNSUPPORTEDALG);
}
return (ISC_R_SUCCESS);
}
else
return (DST_R_UNSUPPORTEDALG);
return (ISC_R_SUCCESS);
}
/***
*** Static methods
***/
/*%
* Allocates a key structure and fills in some of the fields.
*/
static dst_key_t *
{
return (NULL);
return (NULL);
}
if (result != ISC_R_SUCCESS) {
return (NULL);
}
return (key);
}
/*%
* Reads a public key from disk
*/
{
isc_buffer_t b;
unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
/*
* Open the file and read its formatted contents
* File format:
* domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
*/
/* 1500 should be large enough for any key */
if (ret != ISC_R_SUCCESS)
goto cleanup;
if (ret != ISC_R_SUCCESS)
goto cleanup;
if (ret != ISC_R_SUCCESS) \
goto cleanup; \
}
#define BADTOKEN() { \
ret = ISC_R_UNEXPECTEDTOKEN; \
goto cleanup; \
}
/* Read the domain name */
BADTOKEN();
if (ret != ISC_R_SUCCESS)
goto cleanup;
/* Read the next word: either TTL, class, or 'KEY' */
/* If it's a TTL, read the next one */
if (result == ISC_R_SUCCESS)
BADTOKEN();
if (ret == ISC_R_SUCCESS)
BADTOKEN();
else
BADTOKEN();
goto cleanup;
}
if (ret != ISC_R_SUCCESS)
goto cleanup;
keyp);
if (ret != ISC_R_SUCCESS)
goto cleanup;
return (ret);
}
static isc_boolean_t
/* XXXVIX this switch statement is too sparse to gen a jump table. */
case DST_ALG_RSAMD5:
case DST_ALG_RSASHA1:
case DST_ALG_DSA:
case DST_ALG_DH:
return (ISC_FALSE);
case DST_ALG_HMACMD5:
case DST_ALG_GSSAPI:
return (ISC_TRUE);
default:
return (ISC_FALSE);
}
}
/*%
* Writes a public key to disk in DNS format.
*/
static isc_result_t
isc_region_t r;
char filename[ISC_DIR_NAMEMAX];
unsigned char key_array[DST_KEY_MAXSIZE];
char text_array[DST_KEY_MAXTEXTSIZE];
char class_array[10];
if (ret != ISC_R_SUCCESS)
return (ret);
isc_buffer_usedregion(&keyb, &r);
if (ret != ISC_R_SUCCESS)
return (DST_R_INVALIDPUBLICKEY);
if (ret != ISC_R_SUCCESS)
return (DST_R_INVALIDPUBLICKEY);
/*
* Make the filename.
*/
if (ret != ISC_R_SUCCESS)
return (ret);
/*
* Create public key file.
*/
return (DST_R_WRITEERROR);
if (issymmetric(key)) {
access = 0;
&access);
}
if (ret != ISC_R_SUCCESS) {
return (ret);
}
isc_buffer_usedregion(&classb, &r);
if ((type & DST_TYPE_KEY) != 0)
else
isc_buffer_usedregion(&textb, &r);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
const char *suffix = "";
unsigned int len;
if ((type & DST_TYPE_PRIVATE) != 0)
suffix = ".private";
else if (type == DST_TYPE_PUBLIC)
suffix = ".key";
return (ISC_R_NOSPACE);
}
return (ISC_R_NOSPACE);
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_NOSPACE);
suffix);
return (ISC_R_SUCCESS);
}
static isc_result_t
unsigned char dns_array[DST_KEY_MAXSIZE];
isc_region_t r;
if (ret != ISC_R_SUCCESS)
return (ret);
isc_buffer_usedregion(&dnsbuf, &r);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
return (ISC_R_NOMEMORY);
if (isc_buffer_remaininglength(source) > 0) {
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
}
dst_key_free(&key);
return (DST_R_UNSUPPORTEDALG);
}
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
}
}
return (ISC_R_SUCCESS);
}
static isc_result_t
algorithm_status(unsigned int alg) {
if (dst_algorithm_supported(alg))
return (ISC_R_SUCCESS);
#ifndef OPENSSL
alg == DST_ALG_HMACMD5)
return (DST_R_NOCRYPTO);
#endif
return (DST_R_UNSUPPORTEDALG);
}
static isc_result_t
const char *suffix)
{
int n;
olen -= 1;
olen -= 8;
olen -= 4;
if (n < 0)
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
}
unsigned int flags = dst_entropy_flags;
if (pseudo)
}
unsigned int
dst__entropy_status(void) {
return (isc_entropy_status(dst_entropy_pool));
}