1 /* Copyright (C) 2008, 2009, Simon Josefsson
2  * Copyright (C) 2006, 2007, The Written Word, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms,
6  * with or without modification, are permitted provided
7  * that the following conditions are met:
8  *
9  *   Redistributions of source code must retain the above
10  *   copyright notice, this list of conditions and the
11  *   following disclaimer.
12  *
13  *   Redistributions in binary form must reproduce the above
14  *   copyright notice, this list of conditions and the following
15  *   disclaimer in the documentation and/or other materials
16  *   provided with the distribution.
17  *
18  *   Neither the name of the copyright holder nor the names
19  *   of any other contributors may be used to endorse or
20  *   promote products derived from this software without
21  *   specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36  * OF SUCH DAMAGE.
37  */
38 
39 #include "libssh2_priv.h"
40 
41 #ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */
42 
43 #include <string.h>
44 
45 int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,const unsigned char * edata,unsigned long elen,const unsigned char * ndata,unsigned long nlen,const unsigned char * ddata,unsigned long dlen,const unsigned char * pdata,unsigned long plen,const unsigned char * qdata,unsigned long qlen,const unsigned char * e1data,unsigned long e1len,const unsigned char * e2data,unsigned long e2len,const unsigned char * coeffdata,unsigned long coefflen)46 _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
47                  const unsigned char *edata,
48                  unsigned long elen,
49                  const unsigned char *ndata,
50                  unsigned long nlen,
51                  const unsigned char *ddata,
52                  unsigned long dlen,
53                  const unsigned char *pdata,
54                  unsigned long plen,
55                  const unsigned char *qdata,
56                  unsigned long qlen,
57                  const unsigned char *e1data,
58                  unsigned long e1len,
59                  const unsigned char *e2data,
60                  unsigned long e2len,
61                  const unsigned char *coeffdata, unsigned long coefflen)
62 {
63     int rc;
64     (void) e1data;
65     (void) e1len;
66     (void) e2data;
67     (void) e2len;
68 
69     if(ddata) {
70         rc = gcry_sexp_build
71             (rsa, NULL,
72              "(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))",
73              nlen, ndata, elen, edata, dlen, ddata, plen, pdata,
74              qlen, qdata, coefflen, coeffdata);
75     }
76     else {
77         rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
78                              nlen, ndata, elen, edata);
79     }
80     if(rc) {
81         *rsa = NULL;
82         return -1;
83     }
84 
85     return 0;
86 }
87 
88 int
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,const unsigned char * sig,unsigned long sig_len,const unsigned char * m,unsigned long m_len)89 _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
90                          const unsigned char *sig,
91                          unsigned long sig_len,
92                          const unsigned char *m, unsigned long m_len)
93 {
94     unsigned char hash[SHA_DIGEST_LENGTH];
95     gcry_sexp_t s_sig, s_hash;
96     int rc = -1;
97 
98     libssh2_sha1(m, m_len, hash);
99 
100     rc = gcry_sexp_build(&s_hash, NULL,
101                          "(data (flags pkcs1) (hash sha1 %b))",
102                          SHA_DIGEST_LENGTH, hash);
103     if(rc != 0) {
104         return -1;
105     }
106 
107     rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
108     if(rc != 0) {
109         gcry_sexp_release(s_hash);
110         return -1;
111     }
112 
113     rc = gcry_pk_verify(s_sig, s_hash, rsa);
114     gcry_sexp_release(s_sig);
115     gcry_sexp_release(s_hash);
116 
117     return (rc == 0) ? 0 : -1;
118 }
119 
120 int
_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,const unsigned char * p,unsigned long p_len,const unsigned char * q,unsigned long q_len,const unsigned char * g,unsigned long g_len,const unsigned char * y,unsigned long y_len,const unsigned char * x,unsigned long x_len)121 _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
122                  const unsigned char *p,
123                  unsigned long p_len,
124                  const unsigned char *q,
125                  unsigned long q_len,
126                  const unsigned char *g,
127                  unsigned long g_len,
128                  const unsigned char *y,
129                  unsigned long y_len,
130                  const unsigned char *x, unsigned long x_len)
131 {
132     int rc;
133 
134     if(x_len) {
135         rc = gcry_sexp_build
136             (dsactx, NULL,
137              "(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))",
138              p_len, p, q_len, q, g_len, g, y_len, y, x_len, x);
139     }
140     else {
141         rc = gcry_sexp_build(dsactx, NULL,
142                              "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
143                              p_len, p, q_len, q, g_len, g, y_len, y);
144     }
145 
146     if(rc) {
147         *dsactx = NULL;
148         return -1;
149     }
150 
151     return 0;
152 }
153 
154 int
_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,LIBSSH2_SESSION * session,const char * filedata,size_t filedata_len,unsigned const char * passphrase)155 _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
156                                     LIBSSH2_SESSION * session,
157                                     const char *filedata, size_t filedata_len,
158                                     unsigned const char *passphrase)
159 {
160     return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
161                          "Unable to extract private key from memory: "
162                          "Method unimplemented in libgcrypt backend");
163 }
164 
165 int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,LIBSSH2_SESSION * session,const char * filename,unsigned const char * passphrase)166 _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
167                          LIBSSH2_SESSION * session,
168                          const char *filename, unsigned const char *passphrase)
169 {
170     FILE *fp;
171     unsigned char *data, *save_data;
172     unsigned int datalen;
173     int ret;
174     unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
175     unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
176 
177     fp = fopen(filename, FOPEN_READTEXT);
178     if(!fp) {
179         return -1;
180     }
181 
182     ret = _libssh2_pem_parse(session,
183                              "-----BEGIN RSA PRIVATE KEY-----",
184                              "-----END RSA PRIVATE KEY-----",
185                              passphrase,
186                              fp, &data, &datalen);
187     fclose(fp);
188     if(ret) {
189         return -1;
190     }
191 
192     save_data = data;
193 
194     if(_libssh2_pem_decode_sequence(&data, &datalen)) {
195         ret = -1;
196         goto fail;
197     }
198 /* First read Version field (should be 0). */
199     ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
200     if(ret != 0 || (nlen != 1 && *n != '\0')) {
201         ret = -1;
202         goto fail;
203     }
204 
205     ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
206     if(ret != 0) {
207         ret = -1;
208         goto fail;
209     }
210 
211     ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen);
212     if(ret != 0) {
213         ret = -1;
214         goto fail;
215     }
216 
217     ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen);
218     if(ret != 0) {
219         ret = -1;
220         goto fail;
221     }
222 
223     ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
224     if(ret != 0) {
225         ret = -1;
226         goto fail;
227     }
228 
229     ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
230     if(ret != 0) {
231         ret = -1;
232         goto fail;
233     }
234 
235     ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len);
236     if(ret != 0) {
237         ret = -1;
238         goto fail;
239     }
240 
241     ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len);
242     if(ret != 0) {
243         ret = -1;
244         goto fail;
245     }
246 
247     ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen);
248     if(ret != 0) {
249         ret = -1;
250         goto fail;
251     }
252 
253     if(_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
254                          q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
255         ret = -1;
256         goto fail;
257     }
258 
259     ret = 0;
260 
261   fail:
262     LIBSSH2_FREE(session, save_data);
263     return ret;
264 }
265 
266 int
_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,LIBSSH2_SESSION * session,const char * filedata,size_t filedata_len,unsigned const char * passphrase)267 _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
268                                     LIBSSH2_SESSION * session,
269                                     const char *filedata, size_t filedata_len,
270                                     unsigned const char *passphrase)
271 {
272     return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
273                          "Unable to extract private key from memory: "
274                          "Method unimplemented in libgcrypt backend");
275 }
276 
277 int
_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,LIBSSH2_SESSION * session,const char * filename,unsigned const char * passphrase)278 _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
279                          LIBSSH2_SESSION * session,
280                          const char *filename, unsigned const char *passphrase)
281 {
282     FILE *fp;
283     unsigned char *data, *save_data;
284     unsigned int datalen;
285     int ret;
286     unsigned char *p, *q, *g, *y, *x;
287     unsigned int plen, qlen, glen, ylen, xlen;
288 
289     fp = fopen(filename, FOPEN_READTEXT);
290     if(!fp) {
291         return -1;
292     }
293 
294     ret = _libssh2_pem_parse(session,
295                              "-----BEGIN DSA PRIVATE KEY-----",
296                              "-----END DSA PRIVATE KEY-----",
297                              passphrase,
298                              fp, &data, &datalen);
299     fclose(fp);
300     if(ret) {
301         return -1;
302     }
303 
304     save_data = data;
305 
306     if(_libssh2_pem_decode_sequence(&data, &datalen)) {
307         ret = -1;
308         goto fail;
309     }
310 
311 /* First read Version field (should be 0). */
312     ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
313     if(ret != 0 || (plen != 1 && *p != '\0')) {
314         ret = -1;
315         goto fail;
316     }
317 
318     ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
319     if(ret != 0) {
320         ret = -1;
321         goto fail;
322     }
323 
324     ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
325     if(ret != 0) {
326         ret = -1;
327         goto fail;
328     }
329 
330     ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen);
331     if(ret != 0) {
332         ret = -1;
333         goto fail;
334     }
335 
336     ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen);
337     if(ret != 0) {
338         ret = -1;
339         goto fail;
340     }
341 
342     ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen);
343     if(ret != 0) {
344         ret = -1;
345         goto fail;
346     }
347 
348     if(datalen != 0) {
349         ret = -1;
350         goto fail;
351     }
352 
353     if(_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
354         ret = -1;
355         goto fail;
356     }
357 
358     ret = 0;
359 
360   fail:
361     LIBSSH2_FREE(session, save_data);
362     return ret;
363 }
364 
365 int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,libssh2_rsa_ctx * rsactx,const unsigned char * hash,size_t hash_len,unsigned char ** signature,size_t * signature_len)366 _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
367                        libssh2_rsa_ctx * rsactx,
368                        const unsigned char *hash,
369                        size_t hash_len,
370                        unsigned char **signature, size_t *signature_len)
371 {
372     gcry_sexp_t sig_sexp;
373     gcry_sexp_t data;
374     int rc;
375     const char *tmp;
376     size_t size;
377 
378     if(hash_len != SHA_DIGEST_LENGTH) {
379         return -1;
380     }
381 
382     if(gcry_sexp_build(&data, NULL,
383                         "(data (flags pkcs1) (hash sha1 %b))",
384                         hash_len, hash)) {
385         return -1;
386     }
387 
388     rc = gcry_pk_sign(&sig_sexp, data, rsactx);
389 
390     gcry_sexp_release(data);
391 
392     if(rc != 0) {
393         return -1;
394     }
395 
396     data = gcry_sexp_find_token(sig_sexp, "s", 0);
397     if(!data) {
398         return -1;
399     }
400 
401     tmp = gcry_sexp_nth_data(data, 1, &size);
402     if(!tmp) {
403         gcry_sexp_release(data);
404         return -1;
405     }
406 
407     if(tmp[0] == '\0') {
408         tmp++;
409         size--;
410     }
411 
412     *signature = LIBSSH2_ALLOC(session, size);
413     if(!*signature) {
414         gcry_sexp_release(data);
415         return -1;
416     }
417     memcpy(*signature, tmp, size);
418     *signature_len = size;
419 
420     gcry_sexp_release(data);
421 
422     return rc;
423 }
424 
425 int
_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,const unsigned char * hash,unsigned long hash_len,unsigned char * sig)426 _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
427                        const unsigned char *hash,
428                        unsigned long hash_len, unsigned char *sig)
429 {
430     unsigned char zhash[SHA_DIGEST_LENGTH + 1];
431     gcry_sexp_t sig_sexp;
432     gcry_sexp_t data;
433     int ret;
434     const char *tmp;
435     size_t size;
436 
437     if(hash_len != SHA_DIGEST_LENGTH) {
438         return -1;
439     }
440 
441     memcpy(zhash + 1, hash, hash_len);
442     zhash[0] = 0;
443 
444     if(gcry_sexp_build(&data, NULL, "(data (value %b))",
445                        hash_len + 1, zhash)) {
446         return -1;
447     }
448 
449     ret = gcry_pk_sign(&sig_sexp, data, dsactx);
450 
451     gcry_sexp_release(data);
452 
453     if(ret != 0) {
454         return -1;
455     }
456 
457     memset(sig, 0, 40);
458 
459 /* Extract R. */
460 
461     data = gcry_sexp_find_token(sig_sexp, "r", 0);
462     if(!data)
463         goto err;
464 
465     tmp = gcry_sexp_nth_data(data, 1, &size);
466     if(!tmp)
467         goto err;
468 
469     if(tmp[0] == '\0') {
470         tmp++;
471         size--;
472     }
473 
474     if(size < 1 || size > 20)
475         goto err;
476 
477     memcpy(sig + (20 - size), tmp, size);
478 
479     gcry_sexp_release(data);
480 
481 /* Extract S. */
482 
483     data = gcry_sexp_find_token(sig_sexp, "s", 0);
484     if(!data)
485         goto err;
486 
487     tmp = gcry_sexp_nth_data(data, 1, &size);
488     if(!tmp)
489         goto err;
490 
491     if(tmp[0] == '\0') {
492         tmp++;
493         size--;
494     }
495 
496     if(size < 1 || size > 20)
497         goto err;
498 
499     memcpy(sig + 20 + (20 - size), tmp, size);
500     goto out;
501 
502   err:
503     ret = -1;
504 
505   out:
506     if(sig_sexp) {
507         gcry_sexp_release(sig_sexp);
508     }
509     if(data) {
510         gcry_sexp_release(data);
511     }
512     return ret;
513 }
514 
515 int
_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,const unsigned char * sig,const unsigned char * m,unsigned long m_len)516 _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
517                          const unsigned char *sig,
518                          const unsigned char *m, unsigned long m_len)
519 {
520     unsigned char hash[SHA_DIGEST_LENGTH + 1];
521     gcry_sexp_t s_sig, s_hash;
522     int rc = -1;
523 
524     libssh2_sha1(m, m_len, hash + 1);
525     hash[0] = 0;
526 
527     if(gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))",
528                         SHA_DIGEST_LENGTH + 1, hash)) {
529         return -1;
530     }
531 
532     if(gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
533                         20, sig, 20, sig + 20)) {
534         gcry_sexp_release(s_hash);
535         return -1;
536     }
537 
538     rc = gcry_pk_verify(s_sig, s_hash, dsactx);
539     gcry_sexp_release(s_sig);
540     gcry_sexp_release(s_hash);
541 
542     return (rc == 0) ? 0 : -1;
543 }
544 
545 int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,_libssh2_cipher_type (algo),unsigned char * iv,unsigned char * secret,int encrypt)546 _libssh2_cipher_init(_libssh2_cipher_ctx * h,
547                      _libssh2_cipher_type(algo),
548                      unsigned char *iv, unsigned char *secret, int encrypt)
549 {
550     int ret;
551     int cipher = _libssh2_gcry_cipher(algo);
552     int mode = _libssh2_gcry_mode(algo);
553     int keylen = gcry_cipher_get_algo_keylen(cipher);
554 
555     (void) encrypt;
556 
557     ret = gcry_cipher_open(h, cipher, mode, 0);
558     if(ret) {
559         return -1;
560     }
561 
562     ret = gcry_cipher_setkey(*h, secret, keylen);
563     if(ret) {
564         gcry_cipher_close(*h);
565         return -1;
566     }
567 
568     if(mode != GCRY_CIPHER_MODE_STREAM) {
569         int blklen = gcry_cipher_get_algo_blklen(cipher);
570         if(mode == GCRY_CIPHER_MODE_CTR)
571             ret = gcry_cipher_setctr(*h, iv, blklen);
572         else
573             ret = gcry_cipher_setiv(*h, iv, blklen);
574         if(ret) {
575             gcry_cipher_close(*h);
576             return -1;
577         }
578     }
579 
580     return 0;
581 }
582 
583 int
_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,_libssh2_cipher_type (algo),int encrypt,unsigned char * block,size_t blklen)584 _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
585                       _libssh2_cipher_type(algo),
586                       int encrypt, unsigned char *block, size_t blklen)
587 {
588     int cipher = _libssh2_gcry_cipher(algo);
589     int ret;
590 
591     if(encrypt) {
592         ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
593     }
594     else {
595         ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
596     }
597     return ret;
598 }
599 
600 int
_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION * session,unsigned char ** method,size_t * method_len,unsigned char ** pubkeydata,size_t * pubkeydata_len,const char * privatekeydata,size_t privatekeydata_len,const char * passphrase)601 _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
602                                 unsigned char **method,
603                                 size_t *method_len,
604                                 unsigned char **pubkeydata,
605                                 size_t *pubkeydata_len,
606                                 const char *privatekeydata,
607                                 size_t privatekeydata_len,
608                                 const char *passphrase)
609 {
610     return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
611                           "Unable to extract public key from private "
612                           "key in memory: "
613                           "Method unimplemented in libgcrypt backend");
614 }
615 
616 int
_libssh2_pub_priv_keyfile(LIBSSH2_SESSION * session,unsigned char ** method,size_t * method_len,unsigned char ** pubkeydata,size_t * pubkeydata_len,const char * privatekey,const char * passphrase)617 _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
618                           unsigned char **method,
619                           size_t *method_len,
620                           unsigned char **pubkeydata,
621                           size_t *pubkeydata_len,
622                           const char *privatekey,
623                           const char *passphrase)
624 {
625     return _libssh2_error(session, LIBSSH2_ERROR_FILE,
626                          "Unable to extract public key from private key file: "
627                          "Method unimplemented in libgcrypt backend");
628 }
629 
_libssh2_init_aes_ctr(void)630 void _libssh2_init_aes_ctr(void)
631 {
632     /* no implementation */
633 }
634 
635 void
_libssh2_dh_init(_libssh2_dh_ctx * dhctx)636 _libssh2_dh_init(_libssh2_dh_ctx *dhctx)
637 {
638     *dhctx = gcry_mpi_new(0);                   /* Random from client */
639 }
640 
641 int
_libssh2_dh_key_pair(_libssh2_dh_ctx * dhctx,_libssh2_bn * public,_libssh2_bn * g,_libssh2_bn * p,int group_order)642 _libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
643                      _libssh2_bn *g, _libssh2_bn *p, int group_order)
644 {
645     /* Generate x and e */
646     gcry_mpi_randomize(*dhctx, group_order * 8 - 1, GCRY_WEAK_RANDOM);
647     gcry_mpi_powm(public, g, *dhctx, p);
648     return 0;
649 }
650 
651 int
_libssh2_dh_secret(_libssh2_dh_ctx * dhctx,_libssh2_bn * secret,_libssh2_bn * f,_libssh2_bn * p)652 _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
653                    _libssh2_bn *f, _libssh2_bn *p)
654 {
655     /* Compute the shared secret */
656     gcry_mpi_powm(secret, f, *dhctx, p);
657     return 0;
658 }
659 
660 void
_libssh2_dh_dtor(_libssh2_dh_ctx * dhctx)661 _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
662 {
663     gcry_mpi_release(*dhctx);
664     *dhctx = NULL;
665 }
666 
667 #endif /* LIBSSH2_LIBGCRYPT */
668