3 * Catcrypt key-encapsulation
5 * (c) 2004 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28 /*----- Header files ------------------------------------------------------*/
30 #define _FILE_OFFSET_BITS 64
34 #include <mLib/alloc.h>
35 #include <mLib/dstr.h>
36 #include <mLib/report.h>
49 #include "blowfish-cbc.h"
56 /*----- Bulk crypto -------------------------------------------------------*/
58 /* --- NaCl `secretbox' --- */
60 typedef struct naclbox_encctx
{
66 static bulk
*naclbox_init(key
*k
, const char *calg
, const char *halg
)
68 naclbox_encctx
*ctx
= CREATE(naclbox_encctx
);
74 if ((q
= key_getattr(0, k
, "cipher")) != 0) calg
= q
;
75 if (!calg
|| strcmp(calg
, "salsa20") == 0) ctx
->cc
= &salsa20
;
76 else if (strcmp(calg
, "salsa20/12") == 0) ctx
->cc
= &salsa2012
;
77 else if (strcmp(calg
, "salsa20/8") == 0) ctx
->cc
= &salsa208
;
78 else if (strcmp(calg
, "chacha20") == 0) ctx
->cc
= &chacha20
;
79 else if (strcmp(calg
, "chacha12") == 0) ctx
->cc
= &chacha12
;
80 else if (strcmp(calg
, "chacha8") == 0) ctx
->cc
= &chacha8
;
83 "unknown or inappropriate encryption scheme `%s' in key `%s'",
91 static int naclbox_setup(bulk
*b
, gcipher
*cx
)
93 naclbox_encctx
*ctx
= (naclbox_encctx
*)b
;
94 octet k
[SALSA20_KEYSZ
];
96 GC_ENCRYPT(cx
, 0, k
, sizeof(k
));
97 ctx
->c
= GC_INIT(ctx
->cc
, k
, sizeof(k
));
101 static size_t naclbox_overhead(bulk
*b
) { return (POLY1305_TAGSZ
); }
103 static void naclbox_destroy(bulk
*b
)
105 naclbox_encctx
*ctx
= (naclbox_encctx
*)b
;
111 static const char *naclbox_encdoit(bulk
*b
, uint32 seq
, buf
*bb
,
112 const void *p
, size_t sz
)
114 naclbox_encctx
*ctx
= (naclbox_encctx
*)b
;
120 STORE32(t
, seq
); STORE32(t
+ 4, 0); GC_SETIV(ctx
->c
, t
);
121 GC_ENCRYPT(ctx
->c
, 0, t
, POLY1305_KEYSZ
+ POLY1305_MASKSZ
);
122 poly1305_keyinit(&ak
, t
, POLY1305_KEYSZ
);
123 poly1305_macinit(&a
, &ak
, t
+ POLY1305_KEYSZ
);
125 tag
= buf_get(bb
, POLY1305_TAGSZ
); assert(tag
);
126 ct
= buf_get(bb
, sz
); assert(ct
);
127 GC_ENCRYPT(ctx
->c
, p
, ct
, sz
);
128 poly1305_hash(&a
, ct
, sz
);
129 poly1305_done(&a
, tag
);
133 static const char *naclbox_decdoit(bulk
*b
, uint32 seq
, buf
*bb
,
134 const void *p
, size_t sz
)
136 naclbox_encctx
*ctx
= (naclbox_encctx
*)b
;
141 octet
*tag
, *ct
, *pt
;
143 STORE32(t
, seq
); STORE32(t
+ 4, 0); GC_SETIV(ctx
->c
, t
);
144 GC_ENCRYPT(ctx
->c
, 0, t
, POLY1305_KEYSZ
+ POLY1305_MASKSZ
);
145 poly1305_keyinit(&ak
, t
, POLY1305_KEYSZ
);
146 poly1305_macinit(&a
, &ak
, t
+ POLY1305_KEYSZ
);
148 buf_init(&bin
, (/*unconst*/ void *)p
, sz
);
149 if ((tag
= buf_get(&bin
, POLY1305_TAGSZ
)) == 0) return ("no tag");
150 ct
= BCUR(&bin
); sz
= BLEFT(&bin
);
151 poly1305_hash(&a
, ct
, sz
);
152 poly1305_done(&a
, t
);
153 if (!ct_memeq(t
, tag
, POLY1305_TAGSZ
)) return ("authentication failure");
154 pt
= buf_get(bb
, sz
); assert(pt
);
155 GC_DECRYPT(ctx
->c
, ct
, pt
, sz
);
159 static const bulkops naclbox_encops
= {
160 naclbox_init
, naclbox_setup
, naclbox_overhead
,
161 naclbox_encdoit
, naclbox_destroy
162 }, naclbox_decops
= {
163 naclbox_init
, naclbox_setup
, naclbox_overhead
,
164 naclbox_decdoit
, naclbox_destroy
167 /* --- Generic composition --- */
169 typedef struct gencomp_encctx
{
175 octet
*t
; size_t tsz
;
178 static bulk
*gencomp_init(key
*k
, const char *calg
, const char *halg
)
180 gencomp_encctx
*ctx
= CREATE(gencomp_encctx
);
182 dstr d
= DSTR_INIT
, t
= DSTR_INIT
;
186 if ((q
= key_getattr(0, k
, "cipher")) != 0) calg
= q
;
187 if (!calg
) ctx
->cc
= &blowfish_cbc
;
188 else if ((ctx
->cc
= gcipher_byname(calg
)) == 0) {
189 die(EXIT_FAILURE
, "encryption scheme `%s' not found in key `%s'",
194 if ((q
= key_getattr(0, k
, "mac")) == 0) {
195 dstr_putf(&d
, "%s-hmac", halg
);
198 if ((ctx
->mc
= gmac_byname(q
)) == 0) {
200 "message authentication code `%s' not found in key `%s'",
207 static int gencomp_setup(bulk
*b
, gcipher
*cx
)
209 gencomp_encctx
*ctx
= (gencomp_encctx
*)b
;
215 cn
= keysz(0, ctx
->cc
->keysz
); if (cn
> n
) n
= cn
;
216 mn
= keysz(0, ctx
->mc
->keysz
); if (mn
> n
) n
= mn
;
217 ctx
->t
= kd
= xmalloc(n
); ctx
->tsz
= n
;
218 GC_ENCRYPT(cx
, 0, kd
, cn
);
219 ctx
->c
= GC_INIT(ctx
->cc
, kd
, cn
);
220 GC_ENCRYPT(cx
, 0, kd
, mn
);
221 ctx
->m
= GM_KEY(ctx
->mc
, kd
, mn
);
225 static size_t gencomp_overhead(bulk
*b
)
227 gencomp_encctx
*ctx
= (gencomp_encctx
*)b
;
228 return (ctx
->cc
->blksz
+ ctx
->mc
->hashsz
); }
230 static void gencomp_destroy(bulk
*b
)
232 gencomp_encctx
*ctx
= (gencomp_encctx
*)b
;
240 static const char *gencomp_encdoit(bulk
*b
, uint32 seq
, buf
*bb
,
241 const void *p
, size_t sz
)
243 gencomp_encctx
*ctx
= (gencomp_encctx
*)b
;
245 ghash
*h
= GM_INIT(ctx
->m
);
248 if (ctx
->cc
->blksz
) {
249 GC_ENCRYPT(ctx
->cx
, 0, ctx
->t
, ctx
->cc
->blksz
);
250 GC_SETIV(ctx
->c
, ctx
->t
);
252 tag
= buf_get(bb
, ctx
->mc
->hashsz
); assert(tag
);
253 ct
= buf_get(bb
, sz
); assert(ct
);
254 GC_ENCRYPT(ctx
->c
, p
, ct
, sz
);
261 static const char *gencomp_decdoit(bulk
*b
, uint32 seq
, buf
*bb
,
262 const void *p
, size_t sz
)
264 gencomp_encctx
*ctx
= (gencomp_encctx
*)b
;
266 const octet
*tag
, *ct
;
271 buf_init(&bin
, (/*unconst*/ void *)p
, sz
);
272 if ((tag
= buf_get(&bin
, ctx
->mc
->hashsz
)) == 0) return ("no tag");
273 ct
= BCUR(&bin
); sz
= BLEFT(&bin
);
274 pt
= buf_get(bb
, sz
); assert(pt
);
279 ok
= ct_memeq(tag
, GH_DONE(h
, 0), ctx
->mc
->hashsz
);
281 if (!ok
) return ("authentication failure");
283 if (ctx
->cc
->blksz
) {
284 GC_ENCRYPT(ctx
->cx
, 0, ctx
->t
, ctx
->cc
->blksz
);
285 GC_SETIV(ctx
->c
, ctx
->t
);
287 GC_DECRYPT(ctx
->c
, ct
, pt
, sz
);
291 static const bulkops gencomp_encops
= {
292 gencomp_init
, gencomp_setup
, gencomp_overhead
,
293 gencomp_encdoit
, gencomp_destroy
294 }, gencomp_decops
= {
295 gencomp_init
, gencomp_setup
, gencomp_overhead
,
296 gencomp_decdoit
, gencomp_destroy
299 const struct bulktab bulktab
[] = {
300 { "gencomp", &gencomp_encops
, &gencomp_decops
},
301 { "naclbox", &naclbox_encops
, &naclbox_decops
},
305 /*----- Key encapsulation -------------------------------------------------*/
309 typedef struct rsa_encctx
{
314 static kem
*rsa_encinit(key
*k
, void *kd
)
316 rsa_encctx
*re
= CREATE(rsa_encctx
);
317 rsa_pubcreate(&re
->rp
, kd
);
321 static int rsa_encdoit(kem
*k
, dstr
*d
, ghash
*h
)
323 rsa_encctx
*re
= (rsa_encctx
*)k
;
324 mp
*x
= mprand_range(MP_NEW
, re
->rp
.rp
->n
, &rand_global
, 0);
325 mp
*y
= rsa_pubop(&re
->rp
, MP_NEW
, x
);
326 size_t n
= mp_octets(re
->rp
.rp
->n
);
328 mp_storeb(x
, d
->buf
, n
);
329 GH_HASH(h
, d
->buf
, n
);
330 mp_storeb(y
, d
->buf
, n
);
337 static const char *rsa_lengthcheck(mp
*n
)
339 if (mp_bits(n
) < 1020) return ("key too short");
343 static const char *rsa_enccheck(kem
*k
)
345 rsa_encctx
*re
= (rsa_encctx
*)k
;
347 if ((e
= rsa_lengthcheck(re
->rp
.rp
->n
)) != 0) return (e
);
351 static void rsa_encdestroy(kem
*k
)
353 rsa_encctx
*re
= (rsa_encctx
*)k
;
354 rsa_pubdestroy(&re
->rp
);
358 static const kemops rsa_encops
= {
359 rsa_pubfetch
, sizeof(rsa_pub
),
360 rsa_encinit
, rsa_encdoit
, rsa_enccheck
, rsa_encdestroy
363 typedef struct rsa_decctx
{
368 static kem
*rsa_decinit(key
*k
, void *kd
)
370 rsa_decctx
*rd
= CREATE(rsa_decctx
);
371 rsa_privcreate(&rd
->rp
, kd
, &rand_global
);
375 static int rsa_decdoit(kem
*k
, dstr
*d
, ghash
*h
)
377 rsa_decctx
*rd
= (rsa_decctx
*)k
;
378 mp
*x
= mp_loadb(MP_NEW
, d
->buf
, d
->len
);
382 if (MP_CMP(x
, >=, rd
->rp
.rp
->n
)) {
386 n
= mp_octets(rd
->rp
.rp
->n
);
388 x
= rsa_privop(&rd
->rp
, x
, x
);
396 static const char *rsa_deccheck(kem
*k
)
398 rsa_decctx
*rd
= (rsa_decctx
*)k
;
400 if ((e
= rsa_lengthcheck(rd
->rp
.rp
->n
)) != 0) return (e
);
404 static void rsa_decdestroy(kem
*k
)
406 rsa_decctx
*rd
= (rsa_decctx
*)k
;
407 rsa_privdestroy(&rd
->rp
);
411 static const kemops rsa_decops
= {
412 rsa_privfetch
, sizeof(rsa_priv
),
413 rsa_decinit
, rsa_decdoit
, rsa_deccheck
, rsa_decdestroy
416 /* --- DH and EC --- */
418 typedef struct dh_encctx
{
425 static dh_encctx
*dh_doinit(key
*k
, const gprime_param
*gp
, mp
*y
,
426 group
*(*makegroup
)(const gprime_param
*),
429 dh_encctx
*de
= CREATE(dh_encctx
);
433 if ((de
->g
= makegroup(gp
)) == 0)
434 die(EXIT_FAILURE
, "bad %s group in key `%s'", what
, t
.buf
);
436 de
->y
= G_CREATE(de
->g
);
437 if (G_FROMINT(de
->g
, de
->y
, y
))
438 die(EXIT_FAILURE
, "bad public key `%s'", t
.buf
);
443 static dh_encctx
*ec_doinit(key
*k
, const char *cstr
, const ec
*y
)
445 dh_encctx
*de
= CREATE(dh_encctx
);
451 if ((e
= ec_getinfo(&ei
, cstr
)) != 0 ||
452 (de
->g
= group_ec(&ei
)) == 0)
453 die(EXIT_FAILURE
, "bad elliptic curve spec in key `%s': %s", t
.buf
, e
);
455 de
->y
= G_CREATE(de
->g
);
456 if (G_FROMEC(de
->g
, de
->y
, y
))
457 die(EXIT_FAILURE
, "bad public curve point `%s'", t
.buf
);
462 static kem
*dh_encinit(key
*k
, void *kd
)
465 dh_encctx
*de
= dh_doinit(k
, &dp
->dp
, dp
->y
, group_prime
, "prime");
469 static kem
*bindh_encinit(key
*k
, void *kd
)
472 dh_encctx
*de
= dh_doinit(k
, &dp
->dp
, dp
->y
, group_binary
, "binary");
476 static kem
*ec_encinit(key
*k
, void *kd
)
479 dh_encctx
*de
= ec_doinit(k
, ep
->cstr
, &ep
->p
);
483 static int dh_encdoit(kem
*k
, dstr
*d
, ghash
*h
)
485 dh_encctx
*de
= (dh_encctx
*)k
;
486 mp
*r
= mprand_range(MP_NEW
, de
->g
->r
, &rand_global
, 0);
487 ge
*x
= G_CREATE(de
->g
);
488 ge
*y
= G_CREATE(de
->g
);
489 size_t n
= de
->g
->noctets
;
492 G_EXP(de
->g
, x
, de
->g
->g
, r
);
493 G_EXP(de
->g
, y
, de
->y
, r
);
495 buf_init(&b
, d
->buf
, n
);
496 G_TORAW(de
->g
, &b
, y
);
497 GH_HASH(h
, BBASE(&b
), BLEN(&b
));
498 buf_init(&b
, d
->buf
, n
);
499 G_TORAW(de
->g
, &b
, x
);
500 GH_HASH(h
, BBASE(&b
), BLEN(&b
));
508 static const char *dh_enccheck(kem
*k
)
510 dh_encctx
*de
= (dh_encctx
*)k
;
512 if ((e
= G_CHECK(de
->g
, &rand_global
)) != 0)
514 if (group_check(de
->g
, de
->y
))
515 return ("public key not in subgroup");
519 static void dh_encdestroy(kem
*k
)
521 dh_encctx
*de
= (dh_encctx
*)k
;
522 G_DESTROY(de
->g
, de
->y
);
524 G_DESTROYGROUP(de
->g
);
528 static const kemops dh_encops
= {
529 dh_pubfetch
, sizeof(dh_pub
),
530 dh_encinit
, dh_encdoit
, dh_enccheck
, dh_encdestroy
533 static const kemops bindh_encops
= {
534 dh_pubfetch
, sizeof(dh_pub
),
535 bindh_encinit
, dh_encdoit
, dh_enccheck
, dh_encdestroy
538 static const kemops ec_encops
= {
539 ec_pubfetch
, sizeof(ec_pub
),
540 ec_encinit
, dh_encdoit
, dh_enccheck
, dh_encdestroy
543 static kem
*dh_decinit(key
*k
, void *kd
)
546 dh_encctx
*de
= dh_doinit(k
, &dp
->dp
, dp
->y
, group_prime
, "prime");
547 de
->x
= MP_COPY(dp
->x
);
551 static kem
*bindh_decinit(key
*k
, void *kd
)
554 dh_encctx
*de
= dh_doinit(k
, &dp
->dp
, dp
->y
, group_binary
, "binary");
555 de
->x
= MP_COPY(dp
->x
);
559 static kem
*ec_decinit(key
*k
, void *kd
)
562 dh_encctx
*de
= ec_doinit(k
, ep
->cstr
, &ep
->p
);
563 de
->x
= MP_COPY(ep
->x
);
567 static int dh_decdoit(kem
*k
, dstr
*d
, ghash
*h
)
569 dh_encctx
*de
= (dh_encctx
*)k
;
570 ge
*x
= G_CREATE(de
->g
);
571 size_t n
= de
->g
->noctets
;
572 void *p
= xmalloc(n
);
576 buf_init(&b
, d
->buf
, d
->len
);
577 if (G_FROMRAW(de
->g
, &b
, x
) || group_check(de
->g
, x
))
579 G_EXP(de
->g
, x
, x
, de
->x
);
581 G_TORAW(de
->g
, &b
, x
);
582 GH_HASH(h
, BBASE(&b
), BLEN(&b
));
583 GH_HASH(h
, d
->buf
, d
->len
);
591 static const kemops dh_decops
= {
592 dh_privfetch
, sizeof(dh_priv
),
593 dh_decinit
, dh_decdoit
, dh_enccheck
, dh_encdestroy
596 static const kemops bindh_decops
= {
597 dh_privfetch
, sizeof(dh_priv
),
598 bindh_decinit
, dh_decdoit
, dh_enccheck
, dh_encdestroy
601 static const kemops ec_decops
= {
602 ec_privfetch
, sizeof(ec_priv
),
603 ec_decinit
, dh_decdoit
, dh_enccheck
, dh_encdestroy
608 static kem
*x25519_encinit(key
*k
, void *kd
) { return (CREATE(kem
)); }
609 static void x25519_encdestroy(kem
*k
) { DESTROY(k
); }
611 static const char *x25519_enccheck(kem
*k
)
613 x25519_pub
*kd
= k
->kd
;
615 if (kd
->pub
.sz
!= X25519_PUBSZ
)
616 return ("incorrect X25519 public key length");
620 static int x25519_encdoit(kem
*k
, dstr
*d
, ghash
*h
)
622 octet t
[X25519_KEYSZ
], z
[X25519_OUTSZ
];
623 x25519_pub
*kd
= k
->kd
;
625 rand_get(RAND_GLOBAL
, t
, sizeof(t
));
626 dstr_ensure(d
, X25519_PUBSZ
);
627 x25519((octet
*)d
->buf
, t
, x25519_base
);
628 x25519(z
, t
, kd
->pub
.k
);
629 d
->len
+= X25519_PUBSZ
;
630 GH_HASH(h
, d
->buf
, X25519_PUBSZ
);
631 GH_HASH(h
, z
, X25519_OUTSZ
);
635 static const char *x25519_deccheck(kem
*k
)
637 x25519_priv
*kd
= k
->kd
;
639 if (kd
->priv
.sz
!= X25519_KEYSZ
)
640 return ("incorrect X25519 private key length");
641 if (kd
->pub
.sz
!= X25519_PUBSZ
)
642 return ("incorrect X25519 public key length");
646 static int x25519_decdoit(kem
*k
, dstr
*d
, ghash
*h
)
648 octet z
[X25519_OUTSZ
];
649 x25519_priv
*kd
= k
->kd
;
652 if (d
->len
!= X25519_PUBSZ
) goto done
;
653 x25519(z
, kd
->priv
.k
, (const octet
*)d
->buf
);
654 GH_HASH(h
, d
->buf
, X25519_PUBSZ
);
655 GH_HASH(h
, z
, X25519_OUTSZ
);
661 static const kemops x25519_encops
= {
662 x25519_pubfetch
, sizeof(x25519_pub
),
663 x25519_encinit
, x25519_encdoit
, x25519_enccheck
, x25519_encdestroy
666 static const kemops x25519_decops
= {
667 x25519_privfetch
, sizeof(x25519_priv
),
668 x25519_encinit
, x25519_decdoit
, x25519_deccheck
, x25519_encdestroy
671 /* --- Symmetric --- */
673 typedef struct symm_ctx
{
679 static kem
*symm_init(key
*k
, void *kd
)
685 s
= CREATE(symm_ctx
);
688 s
->kp
.e
= KENC_BINARY
;
692 if ((err
= key_unpack(&s
->kp
, kd
, &d
)) != 0) {
693 die(EXIT_FAILURE
, "failed to unpack symmetric key `%s': %s",
694 d
.buf
, key_strerror(err
));
700 static int symm_decdoit(kem
*k
, dstr
*d
, ghash
*h
)
702 symm_ctx
*s
= (symm_ctx
*)k
;
704 GH_HASH(h
, s
->kb
.k
, s
->kb
.sz
);
705 GH_HASH(h
, d
->buf
, d
->len
);
709 static int symm_encdoit(kem
*k
, dstr
*d
, ghash
*h
)
711 dstr_ensure(d
, h
->ops
->c
->hashsz
);
712 d
->len
+= h
->ops
->c
->hashsz
;
713 rand_get(RAND_GLOBAL
, d
->buf
, d
->len
);
714 return (symm_decdoit(k
, d
, h
));
717 static const char *symm_check(kem
*k
) { return (0); }
719 static void symm_destroy(kem
*k
)
720 { symm_ctx
*s
= (symm_ctx
*)k
; key_unpackdone(&s
->kp
); }
722 static const kemops symm_encops
= {
724 symm_init
, symm_encdoit
, symm_check
, symm_destroy
727 static const kemops symm_decops
= {
729 symm_init
, symm_decdoit
, symm_check
, symm_destroy
732 /* --- The switch table --- */
734 const struct kemtab kemtab
[] = {
735 { "rsa", &rsa_encops
, &rsa_decops
},
736 { "dh", &dh_encops
, &dh_decops
},
737 { "bindh", &bindh_encops
, &bindh_decops
},
738 { "ec", &ec_encops
, &ec_decops
},
739 { "x25519", &x25519_encops
, &x25519_decops
},
740 { "symm", &symm_encops
, &symm_decops
},
744 /* --- @getkem@ --- *
746 * Arguments: @key *k@ = the key to load
747 * @const char *app@ = application name
748 * @int wantpriv@ = nonzero if we want to decrypt
749 * @bulk **bc@ = bulk crypto context to set up
751 * Returns: A key-encapsulating thing.
756 kem
*getkem(key
*k
, const char *app
, int wantpriv
, bulk
**bc
)
758 const char *kalg
, *halg
= 0, *balg
= 0;
765 const struct kemtab
*kt
;
767 const struct bulktab
*bt
;
773 /* --- Setup stuff --- */
777 /* --- Get the KEM name --- *
779 * Take the attribute if it's there; otherwise use the key type.
783 if ((q
= key_getattr(0, k
, "kem")) != 0) {
786 } else if (strncmp(k
->type
, app
, n
) == 0 && k
->type
[n
] == '-') {
787 dstr_puts(&d
, k
->type
);
790 die(EXIT_FAILURE
, "no KEM for key `%s'", t
.buf
);
793 /* --- Grab the bulk encryption scheme --- *
795 * Grab it from the KEM if it's there, but override it from the attribute.
798 if (p
&& (p
= strchr(p
, '/')) != 0) {
802 if ((q
= key_getattr(0, k
, "bulk")) != 0)
805 /* --- Grab the hash function --- */
807 if (p
&& (p
= strchr(p
, '/')) != 0) {
811 if ((q
= key_getattr(0, k
, "hash")) != 0)
814 /* --- Instantiate the KEM --- */
816 for (kt
= kemtab
; kt
->name
; kt
++) {
817 if (strcmp(kt
->name
, kalg
) == 0)
820 die(EXIT_FAILURE
, "key encapsulation mechanism `%s' not found in key `%s'",
823 ko
= wantpriv ? kt
->decops
: kt
->encops
;
829 kd
= xmalloc(ko
->kdsz
);
830 kp
= key_fetchinit(ko
->kf
, 0, kd
);
831 if ((e
= key_fetch(kp
, k
)) != 0) {
832 die(EXIT_FAILURE
, "error fetching key `%s': %s",
833 t
.buf
, key_strerror(e
));
836 kk
= ko
->init(k
, kd
);
841 /* --- Set up the bulk crypto --- */
845 else if ((kk
->hc
= ghash_byname(halg
)) == 0) {
846 die(EXIT_FAILURE
, "hash algorithm `%s' not found in key `%s'",
851 if ((q
= key_getattr(0, k
, "kdf")) == 0) {
852 dstr_putf(&d
, "%s-mgf", kk
->hc
->name
);
855 if ((kk
->cxc
= gcipher_byname(q
)) == 0) {
856 die(EXIT_FAILURE
, "encryption scheme (KDF) `%s' not found in key `%s'",
863 for (bt
= bulktab
, bo
= 0; bt
->name
; bt
++) {
864 if (strcmp(balg
, bt
->name
) == 0)
865 { balg
= 0; goto b_found
; }
866 n
= strlen(bt
->name
);
867 if (strncmp(balg
, bt
->name
, n
) == 0 && balg
[n
] == '-')
868 { balg
+= n
+ 1; goto b_found
; }
873 bo
= wantpriv ? bt
->decops
: bt
->encops
;
874 *bc
= bo
->init(k
, balg
, kk
->hc
->name
);
877 /* --- Tidy up --- */
884 /* --- @setupkem@ --- *
886 * Arguments: @kem *k@ = key-encapsulation thing
887 * @dstr *d@ = key-encapsulation data
888 * @bulk *bc@ = bulk crypto context to set up
890 * Returns: Zero on success, nonzero on failure.
892 * Use: Initializes all the various symmetric things from a KEM.
895 int setupkem(kem
*k
, dstr
*d
, bulk
*bc
)
903 if (k
->ops
->doit(k
, d
, h
))
905 n
= keysz(GH_CLASS(h
)->hashsz
, k
->cxc
->keysz
);
909 k
->cx
= GC_INIT(k
->cxc
, kd
, n
);
910 bc
->ops
->setup(bc
, k
->cx
);
918 /* --- @freekem@ --- *
920 * Arguments: @kem *k@ = key-encapsulation thing
924 * Use: Frees up a key-encapsulation thing.
932 key_fetchdone(k
->kp
);
939 /*----- That's all, folks -------------------------------------------------*/