X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/898a4e2555438ff8adb08b4d82690d08715e1048..b817bfc642225b8c3c0b6a7e42d1fb949b61a606:/oaep.c diff --git a/oaep.c b/oaep.c index f69c864..2b9d779 100644 --- a/oaep.c +++ b/oaep.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: oaep.c,v 1.5 2002/01/13 20:20:39 mdw Exp $ + * $Id: oaep.c,v 1.6 2004/04/08 01:36:15 mdw Exp $ * * Optimal asymmetric encryption packing * @@ -27,26 +27,6 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: oaep.c,v $ - * Revision 1.5 2002/01/13 20:20:39 mdw - * Hack the @oaep_decode@ code some more, to make it work again. - * - * Revision 1.4 2002/01/13 13:50:21 mdw - * Allow only one error return, to frustrate Manger's attack against OAEP. - * - * Revision 1.3 2001/02/22 09:04:39 mdw - * Fix memory leaks. - * - * Revision 1.2 2000/07/15 10:01:48 mdw - * Test rig added, based on RIPEMD160-MGF1 test vectors. - * - * Revision 1.1 2000/07/01 11:18:30 mdw - * Support for Optimal Asymmetric Encryption Padding. - * - */ - /*----- Header files ------------------------------------------------------*/ #include @@ -58,25 +38,28 @@ #include "gcipher.h" #include "ghash.h" #include "grand.h" -#include "oaep.h" +#include "rsa.h" /*----- Main code ---------------------------------------------------------*/ /* --- @oaep_encode@ --- * * - * Arguments: @const void *msg@ = pointer to message data + * Arguments: @mp *d@ = where to put the answer + * @const void *m@ = pointer to message data * @size_t msz@ = size of message data - * @void *buf@ = pointer to output buffer - * @size_t sz@ = size of the output buffer + * @octet *b@ = spare buffer + * @size_t sz@ = size of the buffer (big enough) + * @unsigned long nbits@ = length of bits of @n@ * @void *p@ = pointer to OAEP parameter block * - * Returns: Zero if all went well, negative on failure. + * Returns: The encoded plaintext, or null on failure. * * Use: Implements the operation @EME-OAEP-ENCODE@, as defined in * PKCS#1 v. 2.0 (RFC2437). */ -int oaep_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p) +mp *oaep_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) { oaep *o = p; size_t hsz = o->ch->hashsz; @@ -89,50 +72,51 @@ int oaep_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p) /* --- Ensure that everything is sensibly sized --- */ if (2 * hsz + 2 + msz > sz) - return (-1); + return (0); /* --- Make the `seed' value --- */ - q = buf; + q = b; *q++ = 0; sz--; mq = q + hsz; qq = q + sz; - o->r->ops->fill(o->r, q, hsz); + GR_FILL(o->r, q, hsz); /* --- Fill in the rest of the buffer --- */ - h = o->ch->init(); - h->ops->hash(h, o->ep, o->epsz); - h->ops->done(h, mq); - h->ops->destroy(h); + h = GH_INIT(o->ch); + GH_HASH(h, o->ep, o->epsz); + GH_DONE(h, mq); + GH_DESTROY(h); pp = mq + hsz; n = sz - 2 * hsz - msz - 1; memset(pp, 0, n); pp += n; *pp++ = 1; - memcpy(pp, msg, msz); + memcpy(pp, m, msz); /* --- Do the packing --- */ n = sz - hsz; - c = o->cc->init(q, hsz); - c->ops->encrypt(c, mq, mq, n); - c->ops->destroy(c); + c = GC_INIT(o->cc, q, hsz); + GC_ENCRYPT(c, mq, mq, n); + GC_DESTROY(c); - c = o->cc->init(mq, n); - c->ops->encrypt(c, q, q, hsz); - c->ops->destroy(c); + c = GC_INIT(o->cc, mq, n); + GC_ENCRYPT(c, q, q, hsz); + GC_DESTROY(c); /* --- Done --- */ - return (0); + return (mp_loadb(d, b, sz + 1)); } /* --- @oaep_decode@ --- * * - * Arguments: @const void *buf@ = pointer to encoded buffer - * @size_t sz@ = size of the encoded buffer - * @dstr *d@ = pointer to destination string + * Arguments: @mp *m@ = the decrypted message + * @octet *b@ = pointer to a buffer to work in + * @size_t sz@ = the size of the buffer (big enough) + * @unsigned long nbits@ = the number of bits in @n@ * @void *p@ = pointer to OAEP parameter block * * Returns: The length of the output string if successful, negative on @@ -142,7 +126,18 @@ int oaep_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p) * PKCS#1 v. 2.0 (RFC2437). */ -int oaep_decode(const void *buf, size_t sz, dstr *d, void *p) +static int memeq(const void *xx, const void *yy, size_t sz) +{ + int eq = 1; + const octet *x = xx, *y = yy; + while (sz) { /* Always check every byte */ + if (*x++ != *y++) eq = 0; + sz--; + } + return (eq); +} + +int oaep_decode(mp *m, octet *b, size_t sz, unsigned long nbits, void *p) { oaep *o = p; gcipher *c; @@ -152,39 +147,37 @@ int oaep_decode(const void *buf, size_t sz, dstr *d, void *p) unsigned bad = 0; size_t n; size_t hsz = o->ch->hashsz; - int rc = -1; /* --- Ensure that the block is large enough --- */ - if (sz < 2 * hsz) + if (sz < 2 * hsz) /* Doesn't depend on ciphertext */ return (-1); - q = x_alloc(d->a, sz); - memcpy(q, buf, sz); - /* --- Decrypt the message --- */ + mp_storeb(m, b, sz); + q = b; bad = *q; q++; sz--; mq = q + hsz; qq = q + sz; n = sz - hsz; - c = o->cc->init(mq, n); - c->ops->decrypt(c, q, q, hsz); - c->ops->destroy(c); + c = GC_INIT(o->cc, mq, n); + GC_DECRYPT(c, q, q, hsz); + GC_DESTROY(c); - c = o->cc->init(q, hsz); - c->ops->decrypt(c, mq, mq, n); - c->ops->destroy(c); + c = GC_INIT(o->cc, q, hsz); + GC_DECRYPT(c, mq, mq, n); + GC_DESTROY(c); q--; /* --- Check the hash on the encoding parameters --- */ - h = o->ch->init(); - h->ops->hash(h, o->ep, o->epsz); - h->ops->done(h, q); - h->ops->destroy(h); - bad |= memcmp(q, mq, hsz); + h = GH_INIT(o->ch); + GH_HASH(h, o->ep, o->epsz); + GH_DONE(h, q); + GH_DESTROY(h); + bad |= !memeq(q, mq, hsz); /* --- Now find the start of the actual message --- */ @@ -193,98 +186,8 @@ int oaep_decode(const void *buf, size_t sz, dstr *d, void *p) pp++; bad |= (pp >= qq) | (*pp++ != 1); n = qq - pp; - dstr_putm(d, pp, n); - if (!bad) - rc = n; - - x_free(d->a, q); - return (rc); -} - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#include "rmd160.h" -#include "rmd160-mgf.h" - -typedef struct gctx { - grand r; - octet *buf; -} gctx; - -static void rfill(grand *r, void *buf, size_t sz) -{ - gctx *g = (gctx *)r; - memcpy(buf, g->buf, sz); -} - -static const grand_ops gops = { - "const", 0, 0, - 0, 0, - 0, 0, 0, 0, rfill -}; - -static int verify(dstr *v) -{ - gctx gr; - dstr d = DSTR_INIT; - oaep o; - int ok = 1; - - dstr_ensure(&d, v[3].len); - d.len = v[3].len; - gr.r.ops = &gops; - gr.buf = (octet *)v[2].buf; - - o.cc = &rmd160_mgf; - o.ch = &rmd160; - o.r = &gr.r; - o.ep = v[1].buf; - o.epsz = v[1].len; - - if (oaep_encode(v[0].buf, v[0].len, d.buf, d.len, &o) || - memcmp(d.buf, v[3].buf, d.len) != 0) { - ok = 0; - fputs("\nfailure in oaep_encode", stderr); - fputs("\n message = ", stderr); type_hex.dump(&v[0], stderr); - fputs("\n params = ", stderr); type_hex.dump(&v[1], stderr); - fputs("\n salt = ", stderr); type_hex.dump(&v[2], stderr); - fputs("\nexpected = ", stderr); type_hex.dump(&v[3], stderr); - fputs("\n output = ", stderr); type_hex.dump(&d, stderr); - fputc('\n', stderr); - } - - DRESET(&d); - if (oaep_decode(v[3].buf, v[3].len, &d, &o) < 0 || - d.len != v[0].len || memcmp(d.buf, v[0].buf, d.len) != 0) { - ok = 0; - fputs("\nfailure in oaep_decode", stderr); - fputs("\n goop = ", stderr); type_hex.dump(&v[3], stderr); - fputs("\n params = ", stderr); type_hex.dump(&v[1], stderr); - fputs("\n salt = ", stderr); type_hex.dump(&v[2], stderr); - fputs("\nexpected = ", stderr); type_hex.dump(&v[0], stderr); - fputs("\n output = ", stderr); type_hex.dump(&d, stderr); - fputc('\n', stderr); - } - - dstr_destroy(&d); - return (ok); + memmove(q, pp, n); + return (bad ? -1 : n); } -static test_chunk tests[] = { - { "oaep", verify, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } }, - { 0, 0, { 0 } } -}; - -int main(int argc, char *argv[]) -{ - test_run(argc, argv, tests, SRCDIR "/tests/oaep"); - return (0); -} - -#endif - /*----- That's all, folks -------------------------------------------------*/