X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/4155aec42e2aa48af1ebe8f1197f58e2f5830ccf..add23883a6378567be6b7866bc2ff2c32400a346:/server/keymgmt.c diff --git a/server/keymgmt.c b/server/keymgmt.c index d80b81e8..61cba579 100644 --- a/server/keymgmt.c +++ b/server/keymgmt.c @@ -178,18 +178,11 @@ static const kgops *kgtab[] = { static int algs_get(algswitch *a, dstr *e, key_file *kf, key *k) { const char *p; + const bulkcrypto *bulk; char *q, *qq; - dstr d = DSTR_INIT; + dstr d = DSTR_INIT, dd = DSTR_INIT; int rc = -1; - /* --- Symmetric encryption for bulk data --- */ - - if ((p = key_getattr(kf, k, "cipher")) == 0) p = "blowfish-cbc"; - if ((a->c = gcipher_byname(p)) == 0) { - a_format(e, "unknown-cipher", "%s", p, A_END); - goto done; - } - /* --- Hash function --- */ if ((p = key_getattr(kf, k, "hash")) == 0) p = "rmd160"; @@ -210,44 +203,93 @@ static int algs_get(algswitch *a, dstr *e, key_file *kf, key *k) goto done; } - /* --- Message authentication for bulk data --- */ + /* --- Bulk crypto transform --- */ + + if ((p = key_getattr(kf, k, "bulk")) == 0) p = "v0"; + for (bulk = bulktab; bulk->name && strcmp(p, bulk->name) != 0; bulk++); + if (!bulk->name) { + a_format(e, "unknown-bulk-transform", "%s", p, A_END); + goto done; + } + a->bulk = bulk; - if ((p = key_getattr(kf, k, "mac")) != 0) { + /* --- Symmetric encryption for bulk data --- */ + + if (!(a->bulk->prim & BCP_CIPHER)) + a->c = 0; + else { + if ((p = key_getattr(kf, k, "cipher")) == 0) p = "blowfish-cbc"; + if ((a->c = gcipher_byname(p)) == 0) { + a_format(e, "unknown-cipher", "%s", p, A_END); + goto done; + } + } + + /* --- Block cipher for miscellaneous use --- */ + + if (!(a->bulk->prim & BCP_BLKC)) + a->b = 0; + else { + if ((p = key_getattr(kf, k, "blkc")) == 0) { + dstr_reset(&dd); + dstr_puts(&dd, a->c ? a->c->name : "rijndael-"); + if ((q = strrchr(dd.buf, '-')) != 0) *q = 0; + p = dd.buf; + } dstr_reset(&d); - dstr_puts(&d, p); - if ((q = strchr(d.buf, '/')) != 0) - *q++ = 0; - if ((a->m = gmac_byname(d.buf)) == 0) { - a_format(e, "unknown-mac", "%s", d.buf, A_END); + dstr_putf(&d, "%s-ecb", p); + if ((a->b = gcipher_byname(d.buf)) == 0) { + a_format(e, "unknown-blkc", "%s", p, A_END); goto done; } - if (!q) - a->tagsz = a->m->hashsz; - else { - unsigned long n = strtoul(q, &qq, 0); - if (*qq) { - a_format(e, "bad-tag-length-string", "%s", q, A_END); + } + + /* --- Message authentication for bulk data --- */ + + if (!(a->bulk->prim & BCP_MAC)) { + a->m = 0; + a->tagsz = 0; + } else { + if ((p = key_getattr(kf, k, "mac")) != 0) { + dstr_reset(&d); + dstr_puts(&d, p); + if ((q = strchr(d.buf, '/')) != 0) + *q++ = 0; + if ((a->m = gmac_byname(d.buf)) == 0) { + a_format(e, "unknown-mac", "%s", d.buf, A_END); goto done; } - if (n%8 || n/8 > a->m->hashsz) { - a_format(e, "bad-tag-length", "%lu", n, A_END); + if (!q) + a->tagsz = a->m->hashsz; + else { + unsigned long n = strtoul(q, &qq, 0); + if (*qq) { + a_format(e, "bad-tag-length-string", "%s", q, A_END); + goto done; + } + if (n%8 || n/8 > a->m->hashsz) { + a_format(e, "bad-tag-length", "%lu", n, A_END); + goto done; + } + a->tagsz = n/8; + } + } else { + dstr_reset(&d); + dstr_putf(&d, "%s-hmac", a->h->name); + if ((a->m = gmac_byname(d.buf)) == 0) { + a_format(e, "no-hmac-for-hash", "%s", a->h->name, A_END); goto done; } - a->tagsz = n/8; + a->tagsz = a->h->hashsz/2; } - } else { - dstr_reset(&d); - dstr_putf(&d, "%s-hmac", a->h->name); - if ((a->m = gmac_byname(d.buf)) == 0) { - a_format(e, "no-hmac-for-hash", "%s", a->h->name, A_END); - goto done; - } - a->tagsz = a->h->hashsz/2; } + /* --- All done --- */ + rc = 0; done: dstr_destroy(&d); + dstr_destroy(&dd); return (rc); } @@ -267,6 +309,10 @@ done: static int algs_check(algswitch *a, dstr *e, const group *g) { + /* --- Check the bulk crypto transform --- */ + + if (a->bulk->check(a, e)) return (-1); + /* --- Derive the key sizes --- * * * Must ensure that we have non-empty keys. This isn't ideal, but it @@ -275,22 +321,28 @@ static int algs_check(algswitch *a, dstr *e, const group *g) */ a->hashsz = a->h->hashsz; - if ((a->cksz = keysz(a->hashsz, a->c->keysz)) == 0) { + if (a->c && (a->cksz = keysz(a->hashsz, a->c->keysz)) == 0) { a_format(e, "cipher", "%s", a->c->name, "no-key-size", "%lu", (unsigned long)a->hashsz, A_END); return (-1); } - if ((a->mksz = keysz(a->hashsz, a->m->keysz)) == 0) { + if (a->m && (a->mksz = keysz(a->hashsz, a->m->keysz)) == 0) { a_format(e, "mac", "%s", a->m->name, "no-key-size", "%lu", (unsigned long)a->hashsz, A_END); return (-1); } + if (a->b && (a->bksz = keysz(a->hashsz, a->b->keysz)) == 0) { + a_format(e, "blkc", "%.*s", strlen(a->b->name) - 4, a->b->name, + "no-key-size", "%lu", (unsigned long)a->hashsz, + A_END); + return (-1); + } /* --- Derive the data limit --- */ - if (a->c->blksz < 16) a->expsz = MEG(64); + if (a->c && a->c->blksz < 16) a->expsz = MEG(64); else a->expsz = MEG(2048); /* --- Ensure the MGF accepts hashes as keys --- */ @@ -321,7 +373,9 @@ int km_samealgsp(const kdata *kdx, const kdata *kdy) { const algswitch *a = &kdx->algs, *aa = &kdy->algs; - return (group_samep(kdx->g, kdy->g) && a->c == aa->c && + return (group_samep(kdx->g, kdy->g) && + a->bulk == aa->bulk && + a->c == aa->c && a->b == aa->b && a->mgf == aa->mgf && a->h == aa->h && a->m == aa->m && a->tagsz == aa->tagsz); } @@ -368,7 +422,7 @@ static int kh_loadpub(const kgops *ko, key_data *d, kdata *kd, if ((rc = ko->loadpub(d, kd, t, e)) != 0) goto fail_0; if (group_check(kd->g, kd->kpub)) { - a_format(e, "bad-public-group-element"); + a_format(e, "bad-public-group-element", A_END); goto fail_1; } kd->kpriv = 0;