7 * (c) 2004 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 /*----- Header files ------------------------------------------------------*/
32 #define _FILE_OFFSET_BITS 64
36 #include <mLib/report.h>
51 /*----- Main code ---------------------------------------------------------*/
53 /* --- RSA PKCS1 --- */
55 typedef struct rsap1_sigctx
{
61 static sig
*rsap1_siginit(key
*k
, void *kd
, const gchash
*hc
)
63 rsap1_sigctx
*rs
= CREATE(rsap1_sigctx
);
64 rsa_privcreate(&rs
->rp
, kd
, &rand_global
);
65 rs
->p1
.r
= &rand_global
;
67 rs
->p1
.epsz
= strlen(hc
->name
) + 1;
72 static int rsap1_sigdoit(sig
*s
, dstr
*d
)
74 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
76 mp
*m
= rsa_sign(&rs
->rp
, MP_NEW
,
77 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
78 pkcs1_sigencode
, &rs
->p1
);
80 n
= mp_octets(rs
->rp
.rp
->n
); dstr_ensure(d
, n
); mp_storeb(m
, d
->buf
, n
);
81 d
->len
+= n
; mp_drop(m
);
85 static const char *rsa_lengthcheck(mp
*n
)
87 if (mp_bits(n
) < 1024) return ("key too short");
91 static const char *rsap1_sigcheck(sig
*s
)
93 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
95 if ((e
= rsa_lengthcheck(rs
->rp
.rp
->n
)) != 0) return (e
);
99 static void rsap1_sigdestroy(sig
*s
)
101 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
102 rsa_privdestroy(&rs
->rp
);
106 static const sigops rsap1_sig
= {
107 rsa_privfetch
, sizeof(rsa_priv
),
108 rsap1_siginit
, rsap1_sigdoit
, rsap1_sigcheck
, rsap1_sigdestroy
111 typedef struct rsap1_vrfctx
{
117 static sig
*rsap1_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
119 rsap1_vrfctx
*rv
= CREATE(rsap1_vrfctx
);
120 rsa_pubcreate(&rv
->rp
, kd
);
121 rv
->p1
.r
= &rand_global
;
122 rv
->p1
.ep
= hc
->name
;
123 rv
->p1
.epsz
= strlen(hc
->name
) + 1;
128 static int rsap1_vrfdoit(sig
*s
, dstr
*d
)
130 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
131 mp
*m
= mp_loadb(MP_NEW
, d
->buf
, d
->len
);
132 int rc
= rsa_verify(&rv
->rp
, m
,
133 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
134 0, pkcs1_sigdecode
, &rv
->p1
);
139 static const char *rsap1_vrfcheck(sig
*s
)
141 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
143 if ((e
= rsa_lengthcheck(rv
->rp
.rp
->n
)) != 0) return (e
);
147 static void rsap1_vrfdestroy(sig
*s
)
149 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
150 rsa_pubdestroy(&rv
->rp
);
154 static const sigops rsap1_vrf
= {
155 rsa_pubfetch
, sizeof(rsa_pub
),
156 rsap1_vrfinit
, rsap1_vrfdoit
, rsap1_vrfcheck
, rsap1_vrfdestroy
159 /* --- RSA PSS --- */
161 static const gccipher
*getmgf(key
*k
, const gchash
*hc
)
167 if ((mm
= key_getattr(0, k
, "mgf")) == 0) {
168 dstr_putf(&d
, "%s-mgf", hc
->name
);
171 if ((gc
= gcipher_byname(mm
)) == 0)
172 die(EXIT_FAILURE
, "unknown encryption scheme `%s'", mm
);
177 typedef struct rsapss_sigctx
{
183 static sig
*rsapss_siginit(key
*k
, void *kd
, const gchash
*hc
)
185 rsapss_sigctx
*rs
= CREATE(rsapss_sigctx
);
186 rsa_privcreate(&rs
->rp
, kd
, &rand_global
);
187 rs
->p
.r
= &rand_global
;
188 rs
->p
.cc
= getmgf(k
, hc
);
190 rs
->p
.ssz
= hc
->hashsz
;
191 rsa_privdestroy(&rs
->rp
);
195 static int rsapss_sigdoit(sig
*s
, dstr
*d
)
197 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
199 mp
*m
= rsa_sign(&rs
->rp
, MP_NEW
,
200 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
203 n
= mp_octets(rs
->rp
.rp
->n
); dstr_ensure(d
, n
); mp_storeb(m
, d
->buf
, n
);
204 d
->len
+= n
; mp_drop(m
);
208 static const char *rsapss_sigcheck(sig
*s
)
210 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
212 if ((e
= rsa_lengthcheck(rs
->rp
.rp
->n
)) != 0) return (e
);
216 static void rsapss_sigdestroy(sig
*s
)
218 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
219 rsa_privdestroy(&rs
->rp
);
223 static const sigops rsapss_sig
= {
224 rsa_privfetch
, sizeof(rsa_priv
),
225 rsapss_siginit
, rsapss_sigdoit
, rsapss_sigcheck
, rsapss_sigdestroy
228 typedef struct rsapss_vrfctx
{
234 static sig
*rsapss_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
236 rsapss_vrfctx
*rv
= CREATE(rsapss_vrfctx
);
237 rsa_pubcreate(&rv
->rp
, kd
);
238 rv
->p
.r
= &rand_global
;
239 rv
->p
.cc
= getmgf(k
, hc
);
241 rv
->p
.ssz
= hc
->hashsz
;
245 static int rsapss_vrfdoit(sig
*s
, dstr
*d
)
247 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
248 mp
*m
= mp_loadb(MP_NEW
, d
->buf
, d
->len
);
249 int rc
= rsa_verify(&rv
->rp
, m
,
250 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
251 0, pss_decode
, &rv
->p
);
256 static const char *rsapss_vrfcheck(sig
*s
)
258 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
260 if ((e
= rsa_lengthcheck(rv
->rp
.rp
->n
)) != 0) return (e
);
264 static void rsapss_vrfdestroy(sig
*s
)
266 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
267 rsa_pubdestroy(&rv
->rp
);
271 static const sigops rsapss_vrf
= {
272 rsa_pubfetch
, sizeof(rsa_pub
),
273 rsapss_vrfinit
, rsapss_vrfdoit
, rsapss_vrfcheck
, rsapss_vrfdestroy
276 /* --- DSA and ECDSA --- */
278 typedef struct dsa_sigctx
{
283 static void dsa_initcommon(dsa_sigctx
*ds
, const gchash
*hc
,
286 ds
->g
.r
= &rand_global
;
292 static dsa_sigctx
*dsa_doinit(key
*k
, const gprime_param
*gp
,
293 mp
*y
, const gchash
*hc
,
294 group
*(*makegroup
)(const gprime_param
*),
297 dsa_sigctx
*ds
= CREATE(dsa_sigctx
);
301 if ((ds
->g
.g
= makegroup(gp
)) == 0)
302 die(EXIT_FAILURE
, "bad %s group in key `%s'", what
, t
.buf
);
303 ds
->g
.p
= G_CREATE(ds
->g
.g
);
304 if (G_FROMINT(ds
->g
.g
, ds
->g
.p
, y
))
305 die(EXIT_FAILURE
, "bad public key in key `%s'", t
.buf
);
306 dsa_initcommon(ds
, hc
, t
.buf
);
311 static dsa_sigctx
*ecdsa_doinit(key
*k
, const char *cstr
,
312 ec
*y
, const gchash
*hc
)
314 dsa_sigctx
*ds
= CREATE(dsa_sigctx
);
320 if ((e
= ec_getinfo(&ei
, cstr
)) != 0)
321 die(EXIT_FAILURE
, "bad curve in key `%s': %s", t
.buf
, e
);
322 ds
->g
.g
= group_ec(&ei
);
323 ds
->g
.p
= G_CREATE(ds
->g
.g
);
324 if (G_FROMEC(ds
->g
.g
, ds
->g
.p
, y
))
325 die(EXIT_FAILURE
, "bad public key in key `%s'", t
.buf
);
326 dsa_initcommon(ds
, hc
, t
.buf
);
331 static sig
*dsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
334 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
335 ds
->g
.u
= MP_COPY(dp
->x
);
339 static sig
*bindsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
342 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
343 ds
->g
.u
= MP_COPY(dp
->x
);
347 static sig
*ecdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
350 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
351 ds
->g
.u
= MP_COPY(ep
->x
);
355 static int dsa_sigdoit(sig
*s
, dstr
*d
)
357 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
358 gdsa_sig ss
= GDSA_SIG_INIT
;
359 size_t n
= mp_octets(ds
->g
.g
->r
);
361 gdsa_sign(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0), 0);
362 dstr_ensure(d
, 2 * n
);
363 mp_storeb(ss
.r
, d
->buf
, n
);
364 mp_storeb(ss
.s
, d
->buf
+ n
, n
);
366 mp_drop(ss
.r
); mp_drop(ss
.s
);
370 static const char *dsa_sigcheck(sig
*s
)
372 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
374 if ((e
= G_CHECK(ds
->g
.g
, &rand_global
)) != 0)
376 if (group_check(ds
->g
.g
, ds
->g
.p
))
377 return ("public key not in subgroup");
381 static void dsa_sigdestroy(sig
*s
)
383 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
384 G_DESTROY(ds
->g
.g
, ds
->g
.p
);
386 G_DESTROYGROUP(ds
->g
.g
);
390 static const sigops dsa_sig
= {
391 dh_privfetch
, sizeof(dh_priv
),
392 dsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
395 static const sigops bindsa_sig
= {
396 dh_privfetch
, sizeof(dh_priv
),
397 bindsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
400 static const sigops ecdsa_sig
= {
401 ec_privfetch
, sizeof(ec_priv
),
402 ecdsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
405 static sig
*dsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
408 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
412 static sig
*bindsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
415 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
419 static sig
*ecdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
422 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
426 static int dsa_vrfdoit(sig
*s
, dstr
*d
)
428 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
433 ss
.r
= mp_loadb(MP_NEW
, d
->buf
, n
);
434 ss
.s
= mp_loadb(MP_NEW
, d
->buf
+ n
, d
->len
- n
);
435 rc
= gdsa_verify(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0));
436 mp_drop(ss
.r
); mp_drop(ss
.s
);
440 static const sigops dsa_vrf
= {
441 dh_pubfetch
, sizeof(dh_pub
),
442 dsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
445 static const sigops bindsa_vrf
= {
446 dh_pubfetch
, sizeof(dh_pub
),
447 bindsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
450 static const sigops ecdsa_vrf
= {
451 ec_pubfetch
, sizeof(ec_pub
),
452 ecdsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
455 /* --- KCDSA and ECKCDSA --- */
457 static void kcdsa_privkey(dsa_sigctx
*ds
, mp
*x
)
458 { ds
->g
.u
= mp_modinv(MP_NEW
, x
, ds
->g
.g
->r
); }
460 static void kcdsa_sethash(dsa_sigctx
*ds
, const gchash
*hc
)
461 { ds
->s
.h
= gkcdsa_beginhash(&ds
->g
); }
463 static sig
*kcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
466 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
467 kcdsa_privkey(ds
, dp
->x
);
468 kcdsa_sethash(ds
, hc
);
472 static sig
*binkcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
475 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
476 kcdsa_privkey(ds
, dp
->x
);
477 kcdsa_sethash(ds
, hc
);
481 static sig
*eckcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
484 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
485 kcdsa_privkey(ds
, ep
->x
);
486 kcdsa_sethash(ds
, hc
);
490 static int kcdsa_sigdoit(sig
*s
, dstr
*d
)
492 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
493 gkcdsa_sig ss
= GKCDSA_SIG_INIT
;
494 size_t hsz
= ds
->g
.h
->hashsz
, n
= mp_octets(ds
->g
.g
->r
);
496 gkcdsa_sign(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0), 0);
497 dstr_ensure(d
, hsz
+ n
);
498 memcpy(d
->buf
, ss
.r
, hsz
);
499 mp_storeb(ss
.s
, d
->buf
+ hsz
, n
);
501 xfree(ss
.r
); mp_drop(ss
.s
);
505 static const sigops kcdsa_sig
= {
506 dh_privfetch
, sizeof(dh_priv
),
507 kcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
510 static const sigops binkcdsa_sig
= {
511 dh_privfetch
, sizeof(dh_priv
),
512 binkcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
515 static const sigops eckcdsa_sig
= {
516 ec_privfetch
, sizeof(ec_priv
),
517 eckcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
520 static sig
*kcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
523 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
524 kcdsa_sethash(ds
, hc
);
528 static sig
*binkcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
531 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
532 kcdsa_sethash(ds
, hc
);
536 static sig
*eckcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
539 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
540 kcdsa_sethash(ds
, hc
);
544 static int kcdsa_vrfdoit(sig
*s
, dstr
*d
)
546 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
548 size_t hsz
= ds
->g
.h
->hashsz
, n
= d
->len
- hsz
;
553 ss
.r
= (octet
*)d
->buf
;
554 ss
.s
= mp_loadb(MP_NEW
, d
->buf
+ hsz
, n
);
555 rc
= gkcdsa_verify(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0));
560 static const sigops kcdsa_vrf
= {
561 dh_pubfetch
, sizeof(dh_pub
),
562 kcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
565 static const sigops binkcdsa_vrf
= {
566 dh_pubfetch
, sizeof(dh_pub
),
567 binkcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
570 static const sigops eckcdsa_vrf
= {
571 ec_pubfetch
, sizeof(ec_pub
),
572 eckcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
575 /* --- Symmetric message authentication --- */
577 typedef struct mac_ctx
{
585 static sig
*mac_init(key
*k
, void *kd
, const gchash
*hc
)
595 m
->kp
.e
= KENC_BINARY
;
599 if ((mm
= key_getattr(0 /*yik*/, k
, "mac")) == 0) {
600 dstr_putf(&d
, "%s-hmac", hc
->name
);
603 if ((m
->mc
= gmac_byname(mm
)) == 0)
604 die(EXIT_FAILURE
, "unknown message authentication scheme `%s'", mm
);
607 if ((err
= key_unpack(&m
->kp
, kd
, &d
)) != 0) {
608 die(EXIT_FAILURE
, "failed to unpack symmetric key `%s': %s",
609 d
.buf
, key_strerror(err
));
613 if (keysz(m
->kb
.sz
, m
->mc
->keysz
) != m
->kb
.sz
) {
614 die(EXIT_FAILURE
, "bad key size %lu for `%s'",
615 (unsigned long)m
->kb
.sz
, m
->mc
->name
);
617 m
->m
= GM_KEY(m
->mc
, m
->kb
.k
, m
->kb
.sz
);
618 m
->s
.h
= GM_INIT(m
->m
);
622 static int mac_sigdoit(sig
*s
, dstr
*d
)
624 mac_ctx
*m
= (mac_ctx
*)s
;
626 dstr_ensure(d
, m
->mc
->hashsz
);
627 GH_DONE(m
->s
.h
, d
->buf
);
628 d
->len
+= m
->mc
->hashsz
;
632 static int mac_vrfdoit(sig
*s
, dstr
*d
)
634 mac_ctx
*m
= (mac_ctx
*)s
;
637 t
= GH_DONE(m
->s
.h
, 0);
638 if (d
->len
!= m
->mc
->hashsz
|| memcmp(d
->buf
, t
, d
->len
) != 0)
643 static const char *mac_check(sig
*s
) { return (0); }
645 static void mac_destroy(sig
*s
)
647 mac_ctx
*m
= (mac_ctx
*)s
;
649 key_unpackdone(&m
->kp
);
652 static const sigops mac_sig
= {
654 mac_init
, mac_sigdoit
, mac_check
, mac_destroy
657 static const sigops mac_vrf
= {
659 mac_init
, mac_vrfdoit
, mac_check
, mac_destroy
662 /* --- The switch table --- */
664 const struct sigtab sigtab
[] = {
665 { "rsapkcs1", &rsap1_sig
, &rsap1_vrf
, &sha
},
666 { "rsapss", &rsapss_sig
, &rsapss_vrf
, &sha
},
667 { "dsa", &dsa_sig
, &dsa_vrf
, &sha
},
668 { "bindsa", &bindsa_sig
, &bindsa_vrf
, &sha
},
669 { "ecdsa", &ecdsa_sig
, &ecdsa_vrf
, &sha
},
670 { "kcdsa", &kcdsa_sig
, &kcdsa_vrf
, &has160
},
671 { "binkcdsa", &binkcdsa_sig
, &binkcdsa_vrf
, &has160
},
672 { "eckcdsa", &eckcdsa_sig
, &eckcdsa_vrf
, &has160
},
673 { "mac", &mac_sig
, &mac_vrf
, &rmd160
},
677 /* --- @getsig@ --- *
679 * Arguments: @key *k@ = the key to load
680 * @const char *app@ = application name
681 * @int wantpriv@ = nonzero if we want to sign
683 * Returns: A signature-making thing.
685 * Use: Loads a key and starts hashing.
688 sig
*getsig(key
*k
, const char *app
, int wantpriv
)
690 const char *salg
, *halg
= 0;
697 const struct sigtab
*st
;
704 /* --- Setup stuff --- */
708 /* --- Get the signature algorithm --- *
710 * Take the attribute if it's there; otherwise use the key type.
714 if ((q
= key_getattr(0, k
, "sig")) != 0) {
717 } else if (strncmp(k
->type
, app
, n
) == 0 && k
->type
[n
] == '-') {
718 dstr_puts(&d
, k
->type
);
721 die(EXIT_FAILURE
, "no signature algorithm for key `%s'", t
.buf
);
723 /* --- Grab the hash algorithm --- *
725 * Grab it from the signature algorithm if it's there. But override that
726 * from the attribute.
730 if ((p
= strchr(p
, '/')) != 0) {
734 if ((q
= key_getattr(0, k
, "hash")) != 0)
737 /* --- Look up the algorithms in the table --- */
739 for (st
= sigtab
; st
->name
; st
++) {
740 if (strcmp(st
->name
, salg
) == 0)
743 die(EXIT_FAILURE
, "signature algorithm `%s' not found in key `%s'",
749 if ((ch
= ghash_byname(halg
)) == 0) {
750 die(EXIT_FAILURE
, "hash algorithm `%s' not found in key `%s'",
754 so
= wantpriv ? st
->signops
: st
->verifyops
;
756 /* --- Load the key --- */
763 kd
= xmalloc(so
->kdsz
);
764 kp
= key_fetchinit(so
->kf
, 0, kd
);
765 if ((e
= key_fetch(kp
, k
)) != 0) {
766 die(EXIT_FAILURE
, "error fetching key `%s': %s",
767 t
.buf
, key_strerror(e
));
770 s
= so
->init(k
, kd
, ch
);
778 /* --- Free stuff up --- */
785 /* --- @freesig@ --- *
787 * Arguments: @sig *s@ = signature-making thing
791 * Use: Frees up a signature-making thing
800 key_fetchdone(s
->kp
);
806 /*----- That's all, folks -------------------------------------------------*/