1280304Sjkim/*
2280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3280304Sjkim * 2006.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13280304Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include "cryptlib.h"
61238384Sjkim#include <openssl/x509.h>
62238384Sjkim#include <openssl/asn1.h>
63238384Sjkim#include <openssl/dh.h>
64238384Sjkim#include <openssl/bn.h>
65238384Sjkim#include "asn1_locl.h"
66238384Sjkim
67238384Sjkimstatic void int_dh_free(EVP_PKEY *pkey)
68280304Sjkim{
69280304Sjkim    DH_free(pkey->pkey.dh);
70280304Sjkim}
71238384Sjkim
72238384Sjkimstatic int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
73280304Sjkim{
74280304Sjkim    const unsigned char *p, *pm;
75280304Sjkim    int pklen, pmlen;
76280304Sjkim    int ptype;
77280304Sjkim    void *pval;
78280304Sjkim    ASN1_STRING *pstr;
79280304Sjkim    X509_ALGOR *palg;
80280304Sjkim    ASN1_INTEGER *public_key = NULL;
81238384Sjkim
82280304Sjkim    DH *dh = NULL;
83238384Sjkim
84280304Sjkim    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
85280304Sjkim        return 0;
86280304Sjkim    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
87238384Sjkim
88280304Sjkim    if (ptype != V_ASN1_SEQUENCE) {
89280304Sjkim        DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR);
90280304Sjkim        goto err;
91280304Sjkim    }
92238384Sjkim
93280304Sjkim    pstr = pval;
94280304Sjkim    pm = pstr->data;
95280304Sjkim    pmlen = pstr->length;
96238384Sjkim
97280304Sjkim    if (!(dh = d2i_DHparams(NULL, &pm, pmlen))) {
98280304Sjkim        DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
99280304Sjkim        goto err;
100280304Sjkim    }
101238384Sjkim
102280304Sjkim    if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, pklen))) {
103280304Sjkim        DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
104280304Sjkim        goto err;
105280304Sjkim    }
106238384Sjkim
107280304Sjkim    /* We have parameters now set public key */
108280304Sjkim    if (!(dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) {
109280304Sjkim        DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR);
110280304Sjkim        goto err;
111280304Sjkim    }
112238384Sjkim
113280304Sjkim    ASN1_INTEGER_free(public_key);
114280304Sjkim    EVP_PKEY_assign_DH(pkey, dh);
115280304Sjkim    return 1;
116238384Sjkim
117280304Sjkim err:
118280304Sjkim    if (public_key)
119280304Sjkim        ASN1_INTEGER_free(public_key);
120280304Sjkim    if (dh)
121280304Sjkim        DH_free(dh);
122280304Sjkim    return 0;
123238384Sjkim
124280304Sjkim}
125238384Sjkim
126238384Sjkimstatic int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
127280304Sjkim{
128280304Sjkim    DH *dh;
129280304Sjkim    int ptype;
130280304Sjkim    unsigned char *penc = NULL;
131280304Sjkim    int penclen;
132280304Sjkim    ASN1_STRING *str;
133280304Sjkim    ASN1_INTEGER *pub_key = NULL;
134238384Sjkim
135280304Sjkim    dh = pkey->pkey.dh;
136238384Sjkim
137280304Sjkim    str = ASN1_STRING_new();
138284285Sjkim    if (!str) {
139280304Sjkim        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
140280304Sjkim        goto err;
141280304Sjkim    }
142280304Sjkim    str->length = i2d_DHparams(dh, &str->data);
143280304Sjkim    if (str->length <= 0) {
144280304Sjkim        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
145280304Sjkim        goto err;
146280304Sjkim    }
147280304Sjkim    ptype = V_ASN1_SEQUENCE;
148238384Sjkim
149280304Sjkim    pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL);
150280304Sjkim    if (!pub_key)
151280304Sjkim        goto err;
152238384Sjkim
153280304Sjkim    penclen = i2d_ASN1_INTEGER(pub_key, &penc);
154238384Sjkim
155280304Sjkim    ASN1_INTEGER_free(pub_key);
156238384Sjkim
157280304Sjkim    if (penclen <= 0) {
158280304Sjkim        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
159280304Sjkim        goto err;
160280304Sjkim    }
161238384Sjkim
162280304Sjkim    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DH),
163280304Sjkim                               ptype, str, penc, penclen))
164280304Sjkim        return 1;
165238384Sjkim
166280304Sjkim err:
167280304Sjkim    if (penc)
168280304Sjkim        OPENSSL_free(penc);
169280304Sjkim    if (str)
170280304Sjkim        ASN1_STRING_free(str);
171238384Sjkim
172280304Sjkim    return 0;
173280304Sjkim}
174238384Sjkim
175280304Sjkim/*
176280304Sjkim * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that
177280304Sjkim * the AlgorithmIdentifier contains the paramaters, the private key is
178280304Sjkim * explcitly included and the pubkey must be recalculated.
179280304Sjkim */
180238384Sjkim
181238384Sjkimstatic int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
182280304Sjkim{
183280304Sjkim    const unsigned char *p, *pm;
184280304Sjkim    int pklen, pmlen;
185280304Sjkim    int ptype;
186280304Sjkim    void *pval;
187280304Sjkim    ASN1_STRING *pstr;
188280304Sjkim    X509_ALGOR *palg;
189280304Sjkim    ASN1_INTEGER *privkey = NULL;
190238384Sjkim
191280304Sjkim    DH *dh = NULL;
192238384Sjkim
193280304Sjkim    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
194280304Sjkim        return 0;
195238384Sjkim
196280304Sjkim    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
197238384Sjkim
198280304Sjkim    if (ptype != V_ASN1_SEQUENCE)
199280304Sjkim        goto decerr;
200238384Sjkim
201280304Sjkim    if (!(privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)))
202280304Sjkim        goto decerr;
203238384Sjkim
204280304Sjkim    pstr = pval;
205280304Sjkim    pm = pstr->data;
206280304Sjkim    pmlen = pstr->length;
207280304Sjkim    if (!(dh = d2i_DHparams(NULL, &pm, pmlen)))
208280304Sjkim        goto decerr;
209280304Sjkim    /* We have parameters now set private key */
210280304Sjkim    if (!(dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
211280304Sjkim        DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
212280304Sjkim        goto dherr;
213280304Sjkim    }
214280304Sjkim    /* Calculate public key */
215280304Sjkim    if (!DH_generate_key(dh))
216280304Sjkim        goto dherr;
217238384Sjkim
218280304Sjkim    EVP_PKEY_assign_DH(pkey, dh);
219238384Sjkim
220280304Sjkim    ASN1_STRING_clear_free(privkey);
221238384Sjkim
222280304Sjkim    return 1;
223238384Sjkim
224280304Sjkim decerr:
225280304Sjkim    DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR);
226280304Sjkim dherr:
227280304Sjkim    DH_free(dh);
228280304Sjkim    ASN1_STRING_clear_free(privkey);
229280304Sjkim    return 0;
230280304Sjkim}
231238384Sjkim
232238384Sjkimstatic int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
233238384Sjkim{
234280304Sjkim    ASN1_STRING *params = NULL;
235280304Sjkim    ASN1_INTEGER *prkey = NULL;
236280304Sjkim    unsigned char *dp = NULL;
237280304Sjkim    int dplen;
238238384Sjkim
239280304Sjkim    params = ASN1_STRING_new();
240238384Sjkim
241280304Sjkim    if (!params) {
242280304Sjkim        DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
243280304Sjkim        goto err;
244280304Sjkim    }
245238384Sjkim
246280304Sjkim    params->length = i2d_DHparams(pkey->pkey.dh, &params->data);
247280304Sjkim    if (params->length <= 0) {
248280304Sjkim        DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
249280304Sjkim        goto err;
250280304Sjkim    }
251280304Sjkim    params->type = V_ASN1_SEQUENCE;
252238384Sjkim
253280304Sjkim    /* Get private key into integer */
254280304Sjkim    prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
255238384Sjkim
256280304Sjkim    if (!prkey) {
257280304Sjkim        DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR);
258280304Sjkim        goto err;
259280304Sjkim    }
260238384Sjkim
261280304Sjkim    dplen = i2d_ASN1_INTEGER(prkey, &dp);
262238384Sjkim
263280304Sjkim    ASN1_STRING_clear_free(prkey);
264280304Sjkim    prkey = NULL;
265238384Sjkim
266280304Sjkim    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dhKeyAgreement), 0,
267280304Sjkim                         V_ASN1_SEQUENCE, params, dp, dplen))
268280304Sjkim        goto err;
269238384Sjkim
270280304Sjkim    return 1;
271238384Sjkim
272280304Sjkim err:
273280304Sjkim    if (dp != NULL)
274280304Sjkim        OPENSSL_free(dp);
275280304Sjkim    if (params != NULL)
276280304Sjkim        ASN1_STRING_free(params);
277280304Sjkim    if (prkey != NULL)
278280304Sjkim        ASN1_STRING_clear_free(prkey);
279280304Sjkim    return 0;
280238384Sjkim}
281238384Sjkim
282238384Sjkimstatic void update_buflen(const BIGNUM *b, size_t *pbuflen)
283280304Sjkim{
284280304Sjkim    size_t i;
285280304Sjkim    if (!b)
286280304Sjkim        return;
287280304Sjkim    if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
288280304Sjkim        *pbuflen = i;
289280304Sjkim}
290238384Sjkim
291238384Sjkimstatic int dh_param_decode(EVP_PKEY *pkey,
292280304Sjkim                           const unsigned char **pder, int derlen)
293280304Sjkim{
294280304Sjkim    DH *dh;
295280304Sjkim    if (!(dh = d2i_DHparams(NULL, pder, derlen))) {
296280304Sjkim        DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB);
297280304Sjkim        return 0;
298280304Sjkim    }
299280304Sjkim    EVP_PKEY_assign_DH(pkey, dh);
300280304Sjkim    return 1;
301280304Sjkim}
302238384Sjkim
303238384Sjkimstatic int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
304280304Sjkim{
305280304Sjkim    return i2d_DHparams(pkey->pkey.dh, pder);
306280304Sjkim}
307238384Sjkim
308238384Sjkimstatic int do_dh_print(BIO *bp, const DH *x, int indent,
309280304Sjkim                       ASN1_PCTX *ctx, int ptype)
310280304Sjkim{
311280304Sjkim    unsigned char *m = NULL;
312280304Sjkim    int reason = ERR_R_BUF_LIB, ret = 0;
313280304Sjkim    size_t buf_len = 0;
314238384Sjkim
315280304Sjkim    const char *ktype = NULL;
316238384Sjkim
317280304Sjkim    BIGNUM *priv_key, *pub_key;
318238384Sjkim
319280304Sjkim    if (ptype == 2)
320280304Sjkim        priv_key = x->priv_key;
321280304Sjkim    else
322280304Sjkim        priv_key = NULL;
323238384Sjkim
324280304Sjkim    if (ptype > 0)
325280304Sjkim        pub_key = x->pub_key;
326280304Sjkim    else
327280304Sjkim        pub_key = NULL;
328238384Sjkim
329280304Sjkim    update_buflen(x->p, &buf_len);
330238384Sjkim
331280304Sjkim    if (buf_len == 0) {
332280304Sjkim        reason = ERR_R_PASSED_NULL_PARAMETER;
333280304Sjkim        goto err;
334280304Sjkim    }
335238384Sjkim
336280304Sjkim    update_buflen(x->g, &buf_len);
337280304Sjkim    update_buflen(pub_key, &buf_len);
338280304Sjkim    update_buflen(priv_key, &buf_len);
339238384Sjkim
340280304Sjkim    if (ptype == 2)
341280304Sjkim        ktype = "PKCS#3 DH Private-Key";
342280304Sjkim    else if (ptype == 1)
343280304Sjkim        ktype = "PKCS#3 DH Public-Key";
344280304Sjkim    else
345280304Sjkim        ktype = "PKCS#3 DH Parameters";
346238384Sjkim
347280304Sjkim    m = OPENSSL_malloc(buf_len + 10);
348280304Sjkim    if (m == NULL) {
349280304Sjkim        reason = ERR_R_MALLOC_FAILURE;
350280304Sjkim        goto err;
351280304Sjkim    }
352238384Sjkim
353280304Sjkim    BIO_indent(bp, indent, 128);
354280304Sjkim    if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
355280304Sjkim        goto err;
356280304Sjkim    indent += 4;
357238384Sjkim
358280304Sjkim    if (!ASN1_bn_print(bp, "private-key:", priv_key, m, indent))
359280304Sjkim        goto err;
360280304Sjkim    if (!ASN1_bn_print(bp, "public-key:", pub_key, m, indent))
361280304Sjkim        goto err;
362238384Sjkim
363280304Sjkim    if (!ASN1_bn_print(bp, "prime:", x->p, m, indent))
364280304Sjkim        goto err;
365280304Sjkim    if (!ASN1_bn_print(bp, "generator:", x->g, m, indent))
366280304Sjkim        goto err;
367280304Sjkim    if (x->length != 0) {
368280304Sjkim        BIO_indent(bp, indent, 128);
369280304Sjkim        if (BIO_printf(bp, "recommended-private-length: %d bits\n",
370280304Sjkim                       (int)x->length) <= 0)
371280304Sjkim            goto err;
372280304Sjkim    }
373238384Sjkim
374280304Sjkim    ret = 1;
375280304Sjkim    if (0) {
376280304Sjkim err:
377280304Sjkim        DHerr(DH_F_DO_DH_PRINT, reason);
378280304Sjkim    }
379280304Sjkim    if (m != NULL)
380280304Sjkim        OPENSSL_free(m);
381280304Sjkim    return (ret);
382280304Sjkim}
383238384Sjkim
384238384Sjkimstatic int int_dh_size(const EVP_PKEY *pkey)
385280304Sjkim{
386280304Sjkim    return (DH_size(pkey->pkey.dh));
387280304Sjkim}
388238384Sjkim
389238384Sjkimstatic int dh_bits(const EVP_PKEY *pkey)
390280304Sjkim{
391280304Sjkim    return BN_num_bits(pkey->pkey.dh->p);
392280304Sjkim}
393238384Sjkim
394238384Sjkimstatic int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
395280304Sjkim{
396280304Sjkim    if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
397280304Sjkim        BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
398280304Sjkim        return 0;
399280304Sjkim    else
400280304Sjkim        return 1;
401280304Sjkim}
402238384Sjkim
403238384Sjkimstatic int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
404280304Sjkim{
405280304Sjkim    BIGNUM *a;
406238384Sjkim
407280304Sjkim    if ((a = BN_dup(from->pkey.dh->p)) == NULL)
408280304Sjkim        return 0;
409280304Sjkim    if (to->pkey.dh->p != NULL)
410280304Sjkim        BN_free(to->pkey.dh->p);
411280304Sjkim    to->pkey.dh->p = a;
412238384Sjkim
413280304Sjkim    if ((a = BN_dup(from->pkey.dh->g)) == NULL)
414280304Sjkim        return 0;
415280304Sjkim    if (to->pkey.dh->g != NULL)
416280304Sjkim        BN_free(to->pkey.dh->g);
417280304Sjkim    to->pkey.dh->g = a;
418238384Sjkim
419280304Sjkim    return 1;
420280304Sjkim}
421238384Sjkim
422238384Sjkimstatic int dh_missing_parameters(const EVP_PKEY *a)
423280304Sjkim{
424280304Sjkim    if (!a->pkey.dh->p || !a->pkey.dh->g)
425280304Sjkim        return 1;
426280304Sjkim    return 0;
427280304Sjkim}
428238384Sjkim
429238384Sjkimstatic int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
430280304Sjkim{
431280304Sjkim    if (dh_cmp_parameters(a, b) == 0)
432280304Sjkim        return 0;
433280304Sjkim    if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
434280304Sjkim        return 0;
435280304Sjkim    else
436280304Sjkim        return 1;
437280304Sjkim}
438238384Sjkim
439238384Sjkimstatic int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
440280304Sjkim                          ASN1_PCTX *ctx)
441280304Sjkim{
442280304Sjkim    return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
443280304Sjkim}
444238384Sjkim
445238384Sjkimstatic int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent,
446280304Sjkim                           ASN1_PCTX *ctx)
447280304Sjkim{
448280304Sjkim    return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
449280304Sjkim}
450238384Sjkim
451238384Sjkimstatic int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent,
452280304Sjkim                            ASN1_PCTX *ctx)
453280304Sjkim{
454280304Sjkim    return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
455280304Sjkim}
456238384Sjkim
457238384Sjkimint DHparams_print(BIO *bp, const DH *x)
458280304Sjkim{
459280304Sjkim    return do_dh_print(bp, x, 4, NULL, 0);
460280304Sjkim}
461238384Sjkim
462280304Sjkimconst EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
463280304Sjkim    EVP_PKEY_DH,
464280304Sjkim    EVP_PKEY_DH,
465280304Sjkim    0,
466238384Sjkim
467280304Sjkim    "DH",
468280304Sjkim    "OpenSSL PKCS#3 DH method",
469238384Sjkim
470280304Sjkim    dh_pub_decode,
471280304Sjkim    dh_pub_encode,
472280304Sjkim    dh_pub_cmp,
473280304Sjkim    dh_public_print,
474238384Sjkim
475280304Sjkim    dh_priv_decode,
476280304Sjkim    dh_priv_encode,
477280304Sjkim    dh_private_print,
478238384Sjkim
479280304Sjkim    int_dh_size,
480280304Sjkim    dh_bits,
481238384Sjkim
482280304Sjkim    dh_param_decode,
483280304Sjkim    dh_param_encode,
484280304Sjkim    dh_missing_parameters,
485280304Sjkim    dh_copy_parameters,
486280304Sjkim    dh_cmp_parameters,
487280304Sjkim    dh_param_print,
488280304Sjkim    0,
489238384Sjkim
490280304Sjkim    int_dh_free,
491280304Sjkim    0
492280304Sjkim};
493