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 ------------------------------------------------------*/
34 #include <mLib/report.h>
49 /*----- Main code ---------------------------------------------------------*/
51 /* --- RSA PKCS1 --- */
53 typedef struct rsap1_sigctx
{
59 static sig
*rsap1_siginit(key
*k
, void *kd
, const gchash
*hc
)
61 rsap1_sigctx
*rs
= CREATE(rsap1_sigctx
);
62 rsa_privcreate(&rs
->rp
, kd
, &rand_global
);
63 rs
->p1
.r
= &rand_global
;
65 rs
->p1
.epsz
= strlen(hc
->name
) + 1;
70 static int rsap1_sigdoit(sig
*s
, dstr
*d
)
72 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
74 mp
*m
= rsa_sign(&rs
->rp
, MP_NEW
,
75 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
76 pkcs1_sigencode
, &rs
->p1
);
78 n
= mp_octets(rs
->rp
.rp
->n
); dstr_ensure(d
, n
); mp_storeb(m
, d
->buf
, n
);
79 d
->len
+= n
; mp_drop(m
);
83 static const char *rsa_lengthcheck(mp
*n
)
85 if (mp_bits(n
) < 1024) return ("key too short");
89 static const char *rsap1_sigcheck(sig
*s
)
91 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
93 if ((e
= rsa_lengthcheck(rs
->rp
.rp
->n
)) != 0) return (e
);
97 static void rsap1_sigdestroy(sig
*s
)
99 rsap1_sigctx
*rs
= (rsap1_sigctx
*)s
;
100 rsa_privdestroy(&rs
->rp
);
104 static const sigops rsap1_sig
= {
105 rsa_privfetch
, sizeof(rsa_priv
),
106 rsap1_siginit
, rsap1_sigdoit
, rsap1_sigcheck
, rsap1_sigdestroy
109 typedef struct rsap1_vrfctx
{
115 static sig
*rsap1_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
117 rsap1_vrfctx
*rv
= CREATE(rsap1_vrfctx
);
118 rsa_pubcreate(&rv
->rp
, kd
);
119 rv
->p1
.r
= &rand_global
;
120 rv
->p1
.ep
= hc
->name
;
121 rv
->p1
.epsz
= strlen(hc
->name
) + 1;
126 static int rsap1_vrfdoit(sig
*s
, dstr
*d
)
128 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
129 mp
*m
= mp_loadb(MP_NEW
, d
->buf
, d
->len
);
130 int rc
= rsa_verify(&rv
->rp
, m
,
131 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
132 0, pkcs1_sigdecode
, &rv
->p1
);
137 static const char *rsap1_vrfcheck(sig
*s
)
139 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
141 if ((e
= rsa_lengthcheck(rv
->rp
.rp
->n
)) != 0) return (e
);
145 static void rsap1_vrfdestroy(sig
*s
)
147 rsap1_vrfctx
*rv
= (rsap1_vrfctx
*)s
;
148 rsa_pubdestroy(&rv
->rp
);
152 static const sigops rsap1_vrf
= {
153 rsa_pubfetch
, sizeof(rsa_pub
),
154 rsap1_vrfinit
, rsap1_vrfdoit
, rsap1_vrfcheck
, rsap1_vrfdestroy
157 /* --- RSA PSS --- */
159 static const gccipher
*getmgf(key
*k
, const gchash
*hc
)
165 if ((mm
= key_getattr(0, k
, "mgf")) == 0) {
166 dstr_putf(&d
, "%s-mgf", hc
->name
);
169 if ((gc
= gcipher_byname(mm
)) == 0)
170 die(EXIT_FAILURE
, "unknown encryption scheme `%s'", mm
);
175 typedef struct rsapss_sigctx
{
181 static sig
*rsapss_siginit(key
*k
, void *kd
, const gchash
*hc
)
183 rsapss_sigctx
*rs
= CREATE(rsapss_sigctx
);
184 rsa_privcreate(&rs
->rp
, kd
, &rand_global
);
185 rs
->p
.r
= &rand_global
;
186 rs
->p
.cc
= getmgf(k
, hc
);
188 rs
->p
.ssz
= hc
->hashsz
;
189 rsa_privdestroy(&rs
->rp
);
193 static int rsapss_sigdoit(sig
*s
, dstr
*d
)
195 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
197 mp
*m
= rsa_sign(&rs
->rp
, MP_NEW
,
198 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
201 n
= mp_octets(rs
->rp
.rp
->n
); dstr_ensure(d
, n
); mp_storeb(m
, d
->buf
, n
);
202 d
->len
+= n
; mp_drop(m
);
206 static const char *rsapss_sigcheck(sig
*s
)
208 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
210 if ((e
= rsa_lengthcheck(rs
->rp
.rp
->n
)) != 0) return (e
);
214 static void rsapss_sigdestroy(sig
*s
)
216 rsapss_sigctx
*rs
= (rsapss_sigctx
*)s
;
217 rsa_privdestroy(&rs
->rp
);
221 static const sigops rsapss_sig
= {
222 rsa_privfetch
, sizeof(rsa_priv
),
223 rsapss_siginit
, rsapss_sigdoit
, rsapss_sigcheck
, rsapss_sigdestroy
226 typedef struct rsapss_vrfctx
{
232 static sig
*rsapss_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
234 rsapss_vrfctx
*rv
= CREATE(rsapss_vrfctx
);
235 rsa_pubcreate(&rv
->rp
, kd
);
236 rv
->p
.r
= &rand_global
;
237 rv
->p
.cc
= getmgf(k
, hc
);
239 rv
->p
.ssz
= hc
->hashsz
;
243 static int rsapss_vrfdoit(sig
*s
, dstr
*d
)
245 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
246 mp
*m
= mp_loadb(MP_NEW
, d
->buf
, d
->len
);
247 int rc
= rsa_verify(&rv
->rp
, m
,
248 GH_DONE(s
->h
, 0), GH_CLASS(s
->h
)->hashsz
,
249 0, pss_decode
, &rv
->p
);
254 static const char *rsapss_vrfcheck(sig
*s
)
256 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
258 if ((e
= rsa_lengthcheck(rv
->rp
.rp
->n
)) != 0) return (e
);
262 static void rsapss_vrfdestroy(sig
*s
)
264 rsapss_vrfctx
*rv
= (rsapss_vrfctx
*)s
;
265 rsa_pubdestroy(&rv
->rp
);
269 static const sigops rsapss_vrf
= {
270 rsa_pubfetch
, sizeof(rsa_pub
),
271 rsapss_vrfinit
, rsapss_vrfdoit
, rsapss_vrfcheck
, rsapss_vrfdestroy
274 /* --- DSA and ECDSA --- */
276 typedef struct dsa_sigctx
{
281 static void dsa_initcommon(dsa_sigctx
*ds
, const gchash
*hc
,
284 ds
->g
.r
= &rand_global
;
290 static dsa_sigctx
*dsa_doinit(key
*k
, const gprime_param
*gp
,
291 mp
*y
, const gchash
*hc
,
292 group
*(*makegroup
)(const gprime_param
*),
295 dsa_sigctx
*ds
= CREATE(dsa_sigctx
);
299 if ((ds
->g
.g
= makegroup(gp
)) == 0)
300 die(EXIT_FAILURE
, "bad %s group in key `%s'", what
, t
.buf
);
301 ds
->g
.p
= G_CREATE(ds
->g
.g
);
302 if (G_FROMINT(ds
->g
.g
, ds
->g
.p
, y
))
303 die(EXIT_FAILURE
, "bad public key in key `%s'", t
.buf
);
304 dsa_initcommon(ds
, hc
, t
.buf
);
309 static dsa_sigctx
*ecdsa_doinit(key
*k
, const char *cstr
,
310 ec
*y
, const gchash
*hc
)
312 dsa_sigctx
*ds
= CREATE(dsa_sigctx
);
318 if ((e
= ec_getinfo(&ei
, cstr
)) != 0)
319 die(EXIT_FAILURE
, "bad curve in key `%s': %s", t
.buf
, e
);
320 ds
->g
.g
= group_ec(&ei
);
321 ds
->g
.p
= G_CREATE(ds
->g
.g
);
322 if (G_FROMEC(ds
->g
.g
, ds
->g
.p
, y
))
323 die(EXIT_FAILURE
, "bad public key in key `%s'", t
.buf
);
324 dsa_initcommon(ds
, hc
, t
.buf
);
329 static sig
*dsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
332 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
333 ds
->g
.u
= MP_COPY(dp
->x
);
337 static sig
*bindsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
340 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
341 ds
->g
.u
= MP_COPY(dp
->x
);
345 static sig
*ecdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
348 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
349 ds
->g
.u
= MP_COPY(ep
->x
);
353 static int dsa_sigdoit(sig
*s
, dstr
*d
)
355 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
356 gdsa_sig ss
= GDSA_SIG_INIT
;
357 size_t n
= mp_octets(ds
->g
.g
->r
);
359 gdsa_sign(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0), 0);
360 dstr_ensure(d
, 2 * n
);
361 mp_storeb(ss
.r
, d
->buf
, n
);
362 mp_storeb(ss
.s
, d
->buf
+ n
, n
);
364 mp_drop(ss
.r
); mp_drop(ss
.s
);
368 static const char *dsa_sigcheck(sig
*s
)
370 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
372 if ((e
= G_CHECK(ds
->g
.g
, &rand_global
)) != 0)
374 if (group_check(ds
->g
.g
, ds
->g
.p
))
375 return ("public key not in subgroup");
379 static void dsa_sigdestroy(sig
*s
)
381 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
382 G_DESTROY(ds
->g
.g
, ds
->g
.p
);
384 G_DESTROYGROUP(ds
->g
.g
);
388 static const sigops dsa_sig
= {
389 dh_privfetch
, sizeof(dh_priv
),
390 dsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
393 static const sigops bindsa_sig
= {
394 dh_privfetch
, sizeof(dh_priv
),
395 bindsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
398 static const sigops ecdsa_sig
= {
399 ec_privfetch
, sizeof(ec_priv
),
400 ecdsa_siginit
, dsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
403 static sig
*dsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
406 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
410 static sig
*bindsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
413 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
417 static sig
*ecdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
420 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
424 static int dsa_vrfdoit(sig
*s
, dstr
*d
)
426 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
431 ss
.r
= mp_loadb(MP_NEW
, d
->buf
, n
);
432 ss
.s
= mp_loadb(MP_NEW
, d
->buf
+ n
, d
->len
- n
);
433 rc
= gdsa_verify(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0));
434 mp_drop(ss
.r
); mp_drop(ss
.s
);
438 static const sigops dsa_vrf
= {
439 dh_pubfetch
, sizeof(dh_pub
),
440 dsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
443 static const sigops bindsa_vrf
= {
444 dh_pubfetch
, sizeof(dh_pub
),
445 bindsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
448 static const sigops ecdsa_vrf
= {
449 ec_pubfetch
, sizeof(ec_pub
),
450 ecdsa_vrfinit
, dsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
453 /* --- KCDSA and ECKCDSA --- */
455 static void kcdsa_privkey(dsa_sigctx
*ds
, mp
*x
)
456 { ds
->g
.u
= mp_modinv(MP_NEW
, x
, ds
->g
.g
->r
); }
458 static void kcdsa_sethash(dsa_sigctx
*ds
, const gchash
*hc
)
459 { ds
->s
.h
= gkcdsa_beginhash(&ds
->g
); }
461 static sig
*kcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
464 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
465 kcdsa_privkey(ds
, dp
->x
);
466 kcdsa_sethash(ds
, hc
);
470 static sig
*binkcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
473 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
474 kcdsa_privkey(ds
, dp
->x
);
475 kcdsa_sethash(ds
, hc
);
479 static sig
*eckcdsa_siginit(key
*k
, void *kd
, const gchash
*hc
)
482 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
483 kcdsa_privkey(ds
, ep
->x
);
484 kcdsa_sethash(ds
, hc
);
488 static int kcdsa_sigdoit(sig
*s
, dstr
*d
)
490 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
491 gkcdsa_sig ss
= GKCDSA_SIG_INIT
;
492 size_t hsz
= ds
->g
.h
->hashsz
, n
= mp_octets(ds
->g
.g
->r
);
494 gkcdsa_sign(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0), 0);
495 dstr_ensure(d
, hsz
+ n
);
496 memcpy(d
->buf
, ss
.r
, hsz
);
497 mp_storeb(ss
.s
, d
->buf
+ hsz
, n
);
499 xfree(ss
.r
); mp_drop(ss
.s
);
503 static const sigops kcdsa_sig
= {
504 dh_privfetch
, sizeof(dh_priv
),
505 kcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
508 static const sigops binkcdsa_sig
= {
509 dh_privfetch
, sizeof(dh_priv
),
510 binkcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
513 static const sigops eckcdsa_sig
= {
514 ec_privfetch
, sizeof(ec_priv
),
515 eckcdsa_siginit
, kcdsa_sigdoit
, dsa_sigcheck
, dsa_sigdestroy
518 static sig
*kcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
521 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_prime
, "prime");
522 kcdsa_sethash(ds
, hc
);
526 static sig
*binkcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
529 dsa_sigctx
*ds
= dsa_doinit(k
, &dp
->dp
, dp
->y
, hc
, group_binary
, "binary");
530 kcdsa_sethash(ds
, hc
);
534 static sig
*eckcdsa_vrfinit(key
*k
, void *kd
, const gchash
*hc
)
537 dsa_sigctx
*ds
= ecdsa_doinit(k
, ep
->cstr
, &ep
->p
, hc
);
538 kcdsa_sethash(ds
, hc
);
542 static int kcdsa_vrfdoit(sig
*s
, dstr
*d
)
544 dsa_sigctx
*ds
= (dsa_sigctx
*)s
;
546 size_t hsz
= ds
->g
.h
->hashsz
, n
= d
->len
- hsz
;
551 ss
.r
= (octet
*)d
->buf
;
552 ss
.s
= mp_loadb(MP_NEW
, d
->buf
+ hsz
, n
);
553 rc
= gkcdsa_verify(&ds
->g
, &ss
, GH_DONE(ds
->s
.h
, 0));
558 static const sigops kcdsa_vrf
= {
559 dh_pubfetch
, sizeof(dh_pub
),
560 kcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
563 static const sigops binkcdsa_vrf
= {
564 dh_pubfetch
, sizeof(dh_pub
),
565 binkcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
568 static const sigops eckcdsa_vrf
= {
569 ec_pubfetch
, sizeof(ec_pub
),
570 eckcdsa_vrfinit
, kcdsa_vrfdoit
, dsa_sigcheck
, dsa_sigdestroy
573 /* --- The switch table --- */
575 const struct sigtab sigtab
[] = {
576 { "rsapkcs1", &rsap1_sig
, &rsap1_vrf
, &sha
},
577 { "rsapss", &rsapss_sig
, &rsapss_vrf
, &sha
},
578 { "dsa", &dsa_sig
, &dsa_vrf
, &sha
},
579 { "bindsa", &bindsa_sig
, &bindsa_vrf
, &sha
},
580 { "ecdsa", &ecdsa_sig
, &ecdsa_vrf
, &sha
},
581 { "kcdsa", &kcdsa_sig
, &kcdsa_vrf
, &has160
},
582 { "binkcdsa", &binkcdsa_sig
, &binkcdsa_vrf
, &has160
},
583 { "eckcdsa", &eckcdsa_sig
, &eckcdsa_vrf
, &has160
},
587 /* --- @getsig@ --- *
589 * Arguments: @key *k@ = the key to load
590 * @const char *app@ = application name
591 * @int wantpriv@ = nonzero if we want to sign
593 * Returns: A signature-making thing.
595 * Use: Loads a key and starts hashing.
598 sig
*getsig(key
*k
, const char *app
, int wantpriv
)
600 const char *salg
, *halg
= 0;
607 const struct sigtab
*st
;
614 /* --- Setup stuff --- */
618 /* --- Get the signature algorithm --- *
620 * Take the attribute if it's there; otherwise use the key type.
624 if ((q
= key_getattr(0, k
, "sig")) != 0) {
627 } else if (strncmp(k
->type
, app
, n
) == 0 && k
->type
[n
] == '-') {
628 dstr_puts(&d
, k
->type
);
631 die(EXIT_FAILURE
, "no signature algorithm for key `%s'", t
.buf
);
633 /* --- Grab the hash algorithm --- *
635 * Grab it from the signature algorithm if it's there. But override that
636 * from the attribute.
640 if ((p
= strchr(p
, '/')) != 0) {
644 if ((q
= key_getattr(0, k
, "hash")) != 0)
647 /* --- Look up the algorithms in the table --- */
649 for (st
= sigtab
; st
->name
; st
++) {
650 if (strcmp(st
->name
, salg
) == 0)
653 die(EXIT_FAILURE
, "signature algorithm `%s' not found in key `%s'",
659 if ((ch
= ghash_byname(halg
)) == 0) {
660 die(EXIT_FAILURE
, "hash algorithm `%s' not found in key `%s'",
664 so
= wantpriv ? st
->signops
: st
->verifyops
;
666 /* --- Load the key --- */
668 kd
= xmalloc(so
->kdsz
);
669 kp
= key_fetchinit(so
->kf
, 0, kd
);
670 if ((e
= key_fetch(kp
, k
)) != 0)
671 die(EXIT_FAILURE
, "error fetching key `%s': %s", t
.buf
, key_strerror(e
));
672 s
= so
->init(k
, kd
, ch
);
679 /* --- Free stuff up --- */
686 /* --- @freesig@ --- *
688 * Arguments: @sig *s@ = signature-making thing
692 * Use: Frees up a signature-making thing
698 key_fetchdone(s
->kp
);
703 /*----- That's all, folks -------------------------------------------------*/