X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/774d32a5b60c5e7d38fba874a42e2273c49889fc..c080c887f9304819f3df80195ed3670680e3f05c:/pss.c diff --git a/pss.c b/pss.c new file mode 100644 index 0000000..8bbccca --- /dev/null +++ b/pss.c @@ -0,0 +1,236 @@ +/* -*-c-*- + * + * $Id: pss.c,v 1.1 2000/07/20 20:13:38 mdw Exp $ + * + * Probabistic signature scheme + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: pss.c,v $ + * Revision 1.1 2000/07/20 20:13:38 mdw + * Added Bellare and Rogaway's PSS encoding for RSA signatures. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include +#include +#include + +#include "gcipher.h" +#include "ghash.h" +#include "grand.h" +#include "pss.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @pss_presign@ --- * + * + * Arguments: @pss *pp@ = pointer to PSS parameter block + * + * Returns: An initialized generic hash context. + * + * Use: Initializes a hash function for signing with PSS. A salt is + * chosen and written into the parameter block. + */ + +ghash *pss_presign(pss *pp) +{ + size_t hsz = pp->ch->hashsz; + octet *salt = xmalloc(hsz); + ghash *h; + + pp->r->ops->fill(pp->r, salt, hsz); + pp->salt = salt; + h = pp->ch->init(); + h->ops->hash(h, salt, hsz); + return (h); +} + +/* --- @pss_encode@ --- * + * + * Arguments: @const void *msg@ = pointer to message (hash) data + * @size_t msz@ = size of message data + * @void *buf@ = pointer to output buffer + * @size_t sz@ = size of the output buffer + * @void *p@ = pointer to PSS parameter block + * + * Returns: Zero of all went well, negative on failure. + * + * Use: Implements the operation @EMSA-PSS-ENCODE@, as defined in + * PKCS#1 v. 2.1 draft 1. + */ + +int pss_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p) +{ + pss *pp = p; + octet *q, *mq, *qq; + gcipher *c; + size_t hsz = pp->ch->hashsz; + size_t n; + + /* --- Ensure that everything is sensibly sized --- */ + + if (hsz + msz + 1 > sz) + return (-1); + + /* --- Fill in the initial buffer --- */ + + q = buf; + *q++ = 0; sz--; + mq = q + msz; + qq = q + sz; + n = sz - msz; + memcpy(q, msg, msz); + if (pp->salt) + memcpy(mq, pp->salt, hsz); + else + memset(mq, 0, hsz); + memset(mq + hsz, 0, n - hsz); + + /* --- Do the encryption --- */ + + c = pp->cc->init(msg, msz); + c->ops->encrypt(c, mq, mq, n); + c->ops->destroy(c); + + /* --- Done --- */ + + return (0); +} + +/* --- @pss_decode@ --- * + * + * Arguments: @const void *buf@ = pointer to encoded buffer + * @size_t sz@ = size of the encoded byffer + * @dstr *d@ = pointer to destination string + * @void *p@ = pointer to PSS parameter block + * + * Returns: The length of the output string (hash) if successful, + * negative on failure. + * + * Use: Implements most of the operation @EMSA_PSS_VERIFY@, as + * defined in PCSK#1 v. 2.1 draft 1. The salt value is filled + * in ready for hashing of the data to start. + */ + +int pss_decode(const void *buf, size_t sz, dstr *d, void *p) +{ + pss *pp = p; + gcipher *c; + octet *q, *mq, *qq; + octet *ppp; + size_t n; + size_t hsz = pp->ch->hashsz; + int rc = -1; + + /* --- Ensure that the block is large enough --- */ + + if (sz < 2 * hsz + 1) + return (-1); + + q = x_alloc(d->a, sz); + memcpy(q, buf, sz); + + /* --- Recover the salt --- */ + + if (*q++ != 0) + goto fail; + sz--; + mq = q + hsz; + qq = q + sz; + n = sz - hsz; + c = pp->cc->init(q, hsz); + c->ops->decrypt(c, mq, mq, n); + c->ops->destroy(c); + + /* --- Now check the recovery --- */ + + ppp = mq + hsz; + while (ppp < qq) { + if (*ppp) + goto fail; + ppp++; + } + + /* --- Done --- */ + + if (pp->salt) { + if (memcmp(pp->salt, mq, hsz) != 0) + goto fail; + } else { + qq = xmalloc(hsz); + memcpy(qq, mq, hsz); + pp->salt = qq; + } + dstr_putm(d, q, hsz); + rc = hsz; + +fail: + x_free(d->a, q - 1); + return (rc); +} + +/* --- @pss_preverify@ --- * + * + * Arguments: @pss *pp@ = pointer to PSS parameter block + * + * Returns: An initialized generic hash context. + * + * Use: Initializes a hash function for use with PSS. A salt is + * read from the parameter block, where @pss_decode@ should have + * left it. + */ + +ghash *pss_preverify(pss *pp) +{ + size_t hsz = pp->ch->hashsz; + ghash *h = pp->ch->init(); + h->ops->hash(h, pp->salt, hsz); + return (h); +} + +/* --- @pss_done@ --- * + * + * Arguments: @pss *pp@ = pointer to PSS parameter block + * + * Returns: --- + * + * Use: Disposes of a PSS parameter block once it's finished with. + */ + +void pss_done(pss *pp) +{ + if (pp->salt) { + xfree(pp->salt); + pp->salt = 0; + } +} + +/*----- That's all, folks -------------------------------------------------*/