aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind/lib/dst/cylink_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/lib/dst/cylink_link.c')
-rw-r--r--contrib/bind/lib/dst/cylink_link.c676
1 files changed, 676 insertions, 0 deletions
diff --git a/contrib/bind/lib/dst/cylink_link.c b/contrib/bind/lib/dst/cylink_link.c
new file mode 100644
index 000000000000..c7cb2767410b
--- /dev/null
+++ b/contrib/bind/lib/dst/cylink_link.c
@@ -0,0 +1,676 @@
+#ifdef CYLINK_DSS
+static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/cylink_link.c,v 1.7 1999/10/13 16:39:22 vixie Exp $";
+
+/*
+ * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
+ *
+ * Permission to use, copy modify, and distribute this software for any
+ * 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 TRUSTED INFORMATION SYSTEMS
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE.
+ */
+/*
+ * This file contains two components
+ * 1. Interface to the CYLINK library to allow compilation of Bind
+ * with TIS/DNSSEC when CYLINK is not available
+ * all calls to CYLINK are contained inside this file.
+ * 2. The glue to connvert DSA KEYS to and from external formats
+ */
+#include "port_before.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "dst_internal.h"
+#include <toolkit.h>
+
+#include "port_after.h"
+
+typedef struct cylinkkey {
+ char *dk_signer;
+ uchar *dk_p;
+ uchar *dk_q;
+ uchar *dk_g;
+ uchar *dk_x;
+ uchar *dk_y;
+ ushort dk_p_bytes;
+} DSA_Key;
+
+#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
+ k->dk_g == NULL || k->dk_x == NULL)
+#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
+ k->dk_g == NULL || k->dk_y == NULL)
+
+static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len);
+
+static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len);
+
+static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len);
+static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key,
+ const int len);
+static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff,
+ const int buff_len);
+static int dst_cylink_key_from_file_format(DST_KEY *d_key,
+ const char *buff,
+ const int buff_len);
+static void *dst_cylink_free_key_structure(void *key);
+
+static int dst_cylink_generate_keypair(DST_KEY *key, int exp);
+static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
+
+static void *memcpyend(void *dest, const void *src, size_t n, size_t size);
+
+/*
+ * dst_cylink_init() Function to answer set up function pointers for
+ * CYLINK related functions
+ */
+int
+dst_cylink_init()
+{
+ if (dst_t_func[KEY_DSA] != NULL)
+ return (1);
+ dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func));
+ if (dst_t_func[KEY_DSA] == NULL)
+ return (0);
+ memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func));
+ dst_t_func[KEY_DSA]->sign = dst_cylink_sign;
+ dst_t_func[KEY_DSA]->verify = dst_cylink_verify;
+ dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys;
+ dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair;
+ dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure;
+ dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key;
+ dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key;
+ dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format;
+ dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format;
+ SetDataOrder(1);
+ return (1);
+}
+
+/*
+ * dst_cylink_sign
+ * Call CYLINK signing functions to sign a block of data.
+ * There are three steps to signing, INIT (initialize structures),
+ * UPDATE (hash (more) data), FINAL (generate a signature). This
+ * routine performs one or more of these steps.
+ * Parameters
+ * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
+ * algobj structure holds context for a sign done in multiple calls.
+ * context the context to use for this computation
+ * data data to be signed.
+ * len length in bytes of data.
+ * priv_key key to use for signing.
+ * signature location to store signature.
+ * sig_len size in bytes of signature field.
+ * returns
+ * N Success on SIG_MODE_FINAL = returns signature length in bytes
+ * N is 41 for DNS
+ * 0 Success on SIG_MODE_INIT and UPDATE
+ * <0 Failure
+ */
+
+static int
+dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ u_char *signature, const int sig_len)
+{
+ int sign_len = 0;
+ int status;
+ SHA_context *ctx = NULL;
+
+ if (mode & SIG_MODE_INIT)
+ ctx = (SHA_context *) malloc(sizeof(SHA_context));
+ else if (context)
+ ctx = (SHA_context *) *context;
+ if (ctx == NULL)
+ return (-1);
+
+ if (mode & SIG_MODE_INIT)
+ SHAInit(ctx);
+
+ if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
+ status = SHAUpdate(ctx, (u_char *) data, len);
+ if (status != SUCCESS)
+ return (SIGN_UPDATE_FAILURE);
+ }
+ if (mode & SIG_MODE_FINAL) {
+ DSA_Key *key;
+ uchar digest[SHA_LENGTH];
+ uchar rand[SHA_LENGTH];
+ uchar r[SHA_LENGTH], s[SHA_LENGTH];
+
+ if (signature == NULL || sig_len < 2 * SHA_LENGTH)
+ return (SIGN_FINAL_FAILURE);
+ if ((status = SHAFinal(ctx, digest)) != SUCCESS)
+ return (SIGN_FINAL_FAILURE);
+ SAFE_FREE(ctx);
+ if (dkey == NULL || dkey->dk_KEY_struct == NULL)
+ return (-1);
+ key = (DSA_Key *) dkey->dk_KEY_struct;
+ if (NULL_PRIV_KEY(key))
+ return (-2);
+ dst_random(DST_RAND_STD, sizeof(rand), rand);
+ status = GenDSSSignature(key->dk_p_bytes, key->dk_p,
+ key->dk_q, key->dk_g, key->dk_x,
+ rand, r, s, digest);
+ if (status != SUCCESS)
+ return (SIGN_FINAL_FAILURE);
+ *signature = (dkey->dk_key_size - 512)/64;
+ sign_len = 1;
+ memcpy(signature + sign_len, r, SHA_LENGTH);
+ sign_len += SHA_LENGTH;
+ memcpy(signature + sign_len, s, SHA_LENGTH);
+ sign_len += SHA_LENGTH;
+ }
+ else {
+ if (context == NULL)
+ return (-1);
+ *context = (void *) ctx;
+ }
+ return (sign_len);
+}
+
+
+/*
+ * Dst_cylink_verify
+ * Calls CYLINK verification routines. There are three steps to
+ * verification, INIT (initialize structures), UPDATE (hash (more) data),
+ * FINAL (generate a signature). This routine performs one or more of
+ * these steps.
+ * Parameters
+ * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
+ * dkey structure holds context for a verify done in multiple calls.
+ * context algorithm specific context for the current context processing
+ * data data signed.
+ * len length in bytes of data.
+ * pub_key key to use for verify.
+ * signature signature.
+ * sig_len length in bytes of signature.
+ * returns
+ * 0 Success
+ * <0 Failure
+ */
+
+static int
+dst_cylink_verify(const int mode, DST_KEY *dkey, void **context,
+ const u_char *data, const int len,
+ const u_char *signature, const int sig_len)
+{
+ int status;
+ SHA_context *ctx = NULL;
+
+ if (mode & SIG_MODE_INIT)
+ ctx = (SHA_context *) malloc(sizeof(SHA_context));
+ else if (context)
+ ctx = (SHA_context *) *context;
+ if (ctx == NULL)
+ return (-1);
+
+ if (mode & SIG_MODE_INIT)
+ SHAInit(ctx);
+
+ if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
+ status = SHAUpdate(ctx, (u_char *) data, len);
+ if (status != SUCCESS)
+ return (VERIFY_UPDATE_FAILURE);
+ }
+ if (mode & SIG_MODE_FINAL) {
+ DSA_Key *key;
+ uchar digest[SHA_LENGTH];
+ uchar r[SHA_LENGTH], s[SHA_LENGTH];
+
+ if (dkey == NULL || dkey->dk_KEY_struct == NULL)
+ return (-1);
+ key = (DSA_Key *) dkey->dk_KEY_struct;
+ if (NULL_PUB_KEY(key))
+ return (-2);
+ if (signature == NULL || sig_len != (2 * SHA_LENGTH +1))
+ return (SIGN_FINAL_FAILURE);
+ status = SHAFinal(ctx, digest);
+ SAFE_FREE(ctx);
+ if (status != SUCCESS)
+ return (SIGN_FINAL_FAILURE);
+ if (((int)*signature) != ((key->dk_p_bytes -64)/8))
+ return(VERIFY_FINAL_FAILURE);
+
+ memcpy(r, signature +1, SHA_LENGTH);
+ memcpy(s, signature + SHA_LENGTH +1, SHA_LENGTH);
+ status = VerDSSSignature(key->dk_p_bytes, key->dk_p,
+ key->dk_q, key->dk_g, key->dk_y,
+ r, s, digest);
+ if (status != SUCCESS)
+ return (VERIFY_FINAL_FAILURE);
+ }
+ else {
+ if (context == NULL)
+ return (-1);
+ *context = (void *) ctx;
+ }
+ return (0);
+}
+
+
+/*
+ * dst_cylink_to_dns_key
+ * Converts key from DSA to DNS distribution format
+ * This function gets in a pointer to the public key and a work area
+ * to write the key into.
+ * Parameters
+ * public KEY structure
+ * out_str buffer to write encoded key into
+ * out_len size of out_str
+ * Return
+ * N >= 0 length of encoded key
+ * n < 0 error
+ */
+
+static int
+dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str,
+ const int out_len)
+{
+ u_char *op = out_str;
+ int t;
+ DSA_Key *key;
+
+ if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
+ out_len <= 0 || out_str == NULL)
+ return (-1);
+ key = (DSA_Key *) in_key->dk_KEY_struct;
+
+ t = (key->dk_p_bytes - 64) / 8;
+
+ *op++ = t;
+ memcpy(op, key->dk_q, SHA_LENGTH);
+ op += SHA_LENGTH;
+ memcpy(op, key->dk_p, key->dk_p_bytes);
+ op += key->dk_p_bytes;
+ memcpy(op, key->dk_g, key->dk_p_bytes);
+ op += key->dk_p_bytes;
+ memcpy(op, key->dk_y, key->dk_p_bytes);
+ op += key->dk_p_bytes;
+
+ return (op - out_str);
+}
+
+
+/*
+ * dst_cylink_from_dns_key
+ * Converts from a DNS KEY RR format to an RSA KEY.
+ * Parameters
+ * len Length in bytes of DNS key
+ * key DNS key
+ * name Key name
+ * s_key DST structure that will point to the RSA key this routine
+ * will build.
+ * Return
+ * 0 The input key, s_key or name was null.
+ * 1 Success
+ */
+static int
+dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, const int len)
+{
+ int t;
+ const u_char *key_ptr = key;
+ DSA_Key *d_key;
+
+ if (s_key == NULL || len < 0 || key == NULL)
+ return (0);
+
+ if (len == 0) /* process null key */
+ return (1);
+
+ if (key_ptr == NULL)
+ return (0);
+ t = (int) *key_ptr++; /* length of exponent in bytes */
+
+ if ((3 * (t * 8 + 64) + SHA_LENGTH + 1) != len)
+ return (0);
+
+ if ((d_key = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) {
+ EREPORT(("dst_cylink_from_dns_key(): Memory allocation error 1"));
+ return (0);
+ }
+ memset(d_key, 0, sizeof(DSA_Key));
+ s_key->dk_KEY_struct = (void *) d_key;
+ d_key->dk_signer = strdup(s_key->dk_key_name);
+ d_key->dk_p_bytes = 64 + 8 * t;
+
+ if ((d_key->dk_q = (uchar *) malloc(SHA_LENGTH)) == NULL)
+ return (0);
+ memcpy(d_key->dk_q, key_ptr, SHA_LENGTH);
+ key_ptr += SHA_LENGTH;
+
+ if ((d_key->dk_p = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
+ return (0);
+ memcpy(d_key->dk_p, key_ptr, d_key->dk_p_bytes);
+ key_ptr += d_key->dk_p_bytes;
+
+ if ((d_key->dk_g = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
+ return (0);
+ memcpy(d_key->dk_g, key_ptr, d_key->dk_p_bytes);
+ key_ptr += d_key->dk_p_bytes;
+
+ if ((d_key->dk_y = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
+ return (0);
+ memcpy(d_key->dk_y, key_ptr, d_key->dk_p_bytes);
+ key_ptr += d_key->dk_p_bytes;
+
+ s_key->dk_id = dst_s_id_calc(key, len);
+ s_key->dk_key_size = d_key->dk_p_bytes * 8;
+ return (1);
+}
+
+
+/**************************************************************************
+ * dst_cylink_key_to_file_format
+ * Encodes an DSA Key into the portable file format.
+ * Parameters
+ * key DSA KEY structure
+ * buff output buffer
+ * buff_len size of output buffer
+ * Return
+ * 0 Failure - null input rkey
+ * -1 Failure - not enough space in output area
+ * N Success - Length of data returned in buff
+ */
+
+static int
+dst_cylink_key_to_file_format(const DST_KEY *key, char *buff,
+ const int buff_len)
+{
+ char *bp;
+ int len, b_len;
+ DSA_Key *dkey;
+ u_char num[256]; /* More than long enough for DSA keys */
+
+ if (key == NULL || key->dk_KEY_struct == NULL) /* no output */
+ return (0);
+ if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
+ return (-1); /* no OR not enough space in output area */
+
+ dkey = (DSA_Key *) key->dk_KEY_struct;
+
+ memset(buff, 0, buff_len); /* just in case */
+ /* write file header */
+ sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA");
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+ memcpy(num, dkey->dk_p, dkey->dk_p_bytes);
+ if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ",
+ num, dkey->dk_p_bytes)) <= 0)
+ return (-1);
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+ memcpy(num, dkey->dk_q, dkey->dk_p_bytes);
+ if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ",
+ num, SHA_LENGTH)) <= 0)
+ return (-2);
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+ memcpy(num, dkey->dk_g, dkey->dk_p_bytes);
+ if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ",
+ num, dkey->dk_p_bytes)) <= 0)
+ return (-3);
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+ memcpy(num, dkey->dk_x, dkey->dk_p_bytes);
+ if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ",
+ num, SHA_LENGTH)) <= 0)
+ return (-4);
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+ memcpy(num, dkey->dk_y, dkey->dk_p_bytes);
+ if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ",
+ num, dkey->dk_p_bytes)) <= 0)
+ return (-4);
+
+ bp += len;
+ b_len -= len;
+ return (buff_len - b_len);
+}
+
+
+/**************************************************************************
+ * dst_cylink_key_from_file_format
+ * Converts contents of a private key file into a private DSA key.
+ * Parameters
+ * DSA_Key structure to put key into
+ * buff buffer containing the encoded key
+ * buff_len the length of the buffer
+ * Return
+ * n >= 0 Foot print of the key converted
+ * n < 0 Error in conversion
+ */
+
+static int
+dst_cylink_key_from_file_format(DST_KEY *d_key, const char *buff,
+ const int buff_len)
+{
+ u_char s[DSS_LENGTH_MAX];
+ u_char dns[1024];
+ int len, s_len = sizeof(s);
+ int foot = -1, dnslen;
+ const char *p = buff;
+ DSA_Key *dsa_key;
+
+ if (d_key == NULL || buff == NULL || buff_len <= 0)
+ return (-1);
+
+ dsa_key = (DSA_Key *) malloc(sizeof(DSA_Key));
+ if (dsa_key == NULL) {
+ return (-2);
+ }
+ memset(dsa_key, 0, sizeof(*dsa_key));
+ d_key->dk_KEY_struct = (void *) dsa_key;
+
+ if (!dst_s_verify_str(&p, "Prime(p): "))
+ return (-3);
+ memset(s, 0, s_len);
+ if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0)
+ return (-4);
+ dsa_key->dk_p_bytes = len;
+ if ((dsa_key->dk_p = malloc(len)) == NULL)
+ return (-5);
+ memcpy(dsa_key->dk_p, s + s_len - len, len);
+
+ while (*++p && p < (const char *) &buff[buff_len]) {
+ if (dst_s_verify_str(&p, "Subprime(q): ")) {
+ if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
+ return (-6);
+ if ((dsa_key->dk_q = malloc(SHA_LENGTH)) == NULL)
+ return (-7);
+ memcpyend(dsa_key->dk_q, s + s_len - len, len,
+ SHA_LENGTH);
+ } else if (dst_s_verify_str(&p, "Base(g): ")) {
+ if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
+ return (-8);
+ if ((dsa_key->dk_g = malloc(dsa_key->dk_p_bytes))
+ == NULL)
+ return (-9);
+ memcpyend(dsa_key->dk_g, s + s_len - len, len,
+ dsa_key->dk_p_bytes);
+ } else if (dst_s_verify_str(&p, "Private_value(x): ")) {
+ if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
+ return (-10);
+ if ((dsa_key->dk_x = malloc(SHA_LENGTH)) == NULL)
+ return (-11);
+ memcpyend(dsa_key->dk_x, s + s_len - len, len,
+ SHA_LENGTH);
+ } else if (dst_s_verify_str(&p, "Public_value(y): ")) {
+ if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
+ return (-10);
+ if ((dsa_key->dk_y = malloc(dsa_key->dk_p_bytes))
+ == NULL)
+ return (-11);
+ memcpyend(dsa_key->dk_y, s + s_len - len, len,
+ dsa_key->dk_p_bytes);
+ } else {
+ EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p));
+ return (-12);
+ }
+ } /* while p */
+
+ d_key->dk_key_size = dsa_key->dk_p_bytes * 8;
+ dnslen = d_key->dk_func->to_dns_key(d_key, dns, sizeof(dns));
+ foot = dst_s_id_calc(dns, dnslen);
+
+ return (foot);
+}
+
+
+/**************************************************************************
+ * dst_cylink_free_key_structure
+ * Frees all dynamicly allocated structures in DSA_Key.
+ */
+
+static void *
+dst_cylink_free_key_structure(void *key)
+{
+ DSA_Key *d_key = (DSA_Key *) key;
+ if (d_key != NULL) {
+ SAFE_FREE(d_key->dk_signer);
+ SAFE_FREE(d_key->dk_p);
+ SAFE_FREE(d_key->dk_q);
+ SAFE_FREE(d_key->dk_g);
+ SAFE_FREE(d_key->dk_x);
+ SAFE_FREE(d_key->dk_y);
+ SAFE_FREE(d_key);
+ }
+ return (NULL);
+}
+
+
+/**************************************************************************
+ * dst_cylink_generate_keypair
+ * Generates unique keys that are hard to predict.
+ * Parameters
+ * key generic Key structure
+ * exp the public exponent
+ * Return
+ * 0 Failure
+ * 1 Success
+ */
+
+static int
+dst_cylink_generate_keypair(DST_KEY *key, int nothing)
+{
+ int status, dnslen, n;
+ DSA_Key *dsa;
+ u_char rand[SHA_LENGTH];
+ u_char dns[1024];
+
+ if (key == NULL || key->dk_alg != KEY_DSA)
+ return (0);
+
+ if ((dsa = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) {
+ EREPORT(("dst_cylink_generate_keypair: Memory allocation error 3"));
+ return (0);
+ }
+ memset(dsa, 0, sizeof(*dsa));
+
+ dsa->dk_p_bytes = key->dk_key_size / 8;
+ dsa->dk_p = (uchar *) malloc(dsa->dk_p_bytes);
+ dsa->dk_q = (uchar *) malloc(SHA_LENGTH);
+ dsa->dk_g = (uchar *) malloc(dsa->dk_p_bytes);
+ dsa->dk_x = (uchar *) malloc(SHA_LENGTH);
+ dsa->dk_y = (uchar *) malloc(dsa->dk_p_bytes);
+ if (!dsa->dk_p || !dsa->dk_q || !dsa->dk_g || !dsa->dk_x || !dsa->dk_y) {
+ EREPORT(("dst_cylink_generate_keypair: Memory allocation error 4"));
+ return (0);
+ }
+ n = dst_random(DST_RAND_KEY, sizeof(rand), rand);
+ if (n != sizeof(rand))
+ return (0);
+ status = GenDSSParameters(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q,
+ dsa->dk_g, rand, NULL);
+ if (status != SUCCESS)
+ return (0);
+
+ status = GenDSSKey(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, dsa->dk_g,
+ dsa->dk_x, dsa->dk_y, rand);
+ if (status != SUCCESS)
+ return (0);
+ memset(rand, 0, sizeof(rand));
+ key->dk_KEY_struct = (void *) dsa;
+ dnslen = key->dk_func->to_dns_key(key, dns, sizeof(dns));
+ key->dk_id = dst_s_id_calc(dns, dnslen);
+ return (1);
+}
+
+
+/*
+ * dst_cylink_compare_keys
+ * Compare two keys for equality.
+ * Return
+ * 0 The keys are equal
+ * NON-ZERO The keys are not equal
+ */
+
+static int
+dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
+{
+ int status;
+ DSA_Key *dkey1 = (DSA_Key *) key1->dk_KEY_struct;
+ DSA_Key *dkey2 = (DSA_Key *) key2->dk_KEY_struct;
+
+ if (dkey1 == NULL && dkey2 == NULL)
+ return (0);
+ else if (dkey1 == NULL)
+ return (2);
+ else if (dkey2 == NULL)
+ return(1);
+
+ if (dkey1->dk_p_bytes != dkey2->dk_p_bytes)
+ return (201);
+ status = memcmp(dkey1->dk_p, dkey2->dk_p, dkey1->dk_p_bytes) ||
+ memcmp(dkey1->dk_q, dkey2->dk_q, SHA_LENGTH) ||
+ memcmp(dkey1->dk_g, dkey2->dk_g, dkey1->dk_p_bytes) ||
+ memcmp(dkey1->dk_y, dkey2->dk_y, dkey1->dk_p_bytes);
+ if (status)
+ return (status);
+ if (dkey1->dk_x || dkey2->dk_x) {
+ if (dkey1->dk_x == NULL || dkey2->dk_x == NULL)
+ return (202);
+ return (memcmp(dkey1->dk_x, dkey2->dk_x, dkey1->dk_p_bytes));
+ } else
+ return (0);
+}
+
+static void *
+memcpyend(void *dest, const void *src, size_t n, size_t size) {
+ if (n < size)
+ memset(dest, 0, size - n);
+ memcpy((char *)dest + size - n, src, n);
+ return dest;
+}
+
+#else
+int
+dst_cylink_init()
+{
+ return (0);
+}
+#endif /* CYLINK */