X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/898a4e2555438ff8adb08b4d82690d08715e1048..b817bfc642225b8c3c0b6a7e42d1fb949b61a606:/pkcs1.c diff --git a/pkcs1.c b/pkcs1.c index dd19569..3460467 100644 --- a/pkcs1.c +++ b/pkcs1.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: pkcs1.c,v 1.3 2000/10/08 12:07:04 mdw Exp $ + * $Id: pkcs1.c,v 1.4 2004/04/08 01:36:15 mdw Exp $ * * PKCS#1 1.5 packing * @@ -27,21 +27,6 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: pkcs1.c,v $ - * Revision 1.3 2000/10/08 12:07:04 mdw - * Don't do arithmetic on @void *@ pointers. - * - * Revision 1.2 2000/07/05 17:49:48 mdw - * Fix decoding functions, so that they don't run off the end of the - * buffer. - * - * Revision 1.1 2000/07/01 11:17:38 mdw - * New support for PKCS#1 message encoding. - * - */ - /*----- Header files ------------------------------------------------------*/ #include @@ -50,62 +35,71 @@ #include #include "grand.h" -#include "pkcs1.h" +#include "rsa.h" /*----- Main code ---------------------------------------------------------*/ /* --- @pkcs1_cryptencode@ --- * * - * 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 PKCS1 parameter block * - * Returns: Zero if all went well, negative on failure. + * Returns: The encoded result, or null. * * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined * in PKCS#1 v. 2.0 (RFC2437). */ -int pkcs1_cryptencode(const void *msg, size_t msz, void *buf, size_t sz, - void *p) +mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) { pkcs1 *pp = p; grand *r = pp->r; - octet *q, *qq; + octet *q; size_t i, n; /* --- Ensure that the buffer is sensibly sized --- */ if (pp->epsz + msz + 11 > sz) - return (-1); + return (0); - /* --- Fill in the buffer --- */ + /* --- Allocate the buffer and fill it in --- */ - q = buf; - qq = q + sz; - *q++ = 0; - *q++ = 2; + q = b; + *q++ = 0x00; + *q++ = 0x02; n = sz - msz - pp->epsz - 3; - r->ops->fill(r, q, n); + GR_FILL(r, q, n); for (i = 0; i < n; i++) { if (*q == 0) *q = r->ops->range(r, 255) + 1; q++; } *q++ = 0; - memcpy(q, pp->ep, pp->epsz); - q += pp->epsz; - memcpy(q, msg, msz); - return (0); + if (pp->ep) { + memcpy(q, pp->ep, pp->epsz); + q += pp->epsz; + } + memcpy(q, m, msz); + q += msz; + assert(q == b + sz); + + /* --- Collect the result --- */ + + return (mp_loadb(d, b, sz)); } /* --- @pkcs1_cryptdecode@ --- * * - * 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 PKCS1 parameter block * * Returns: The length of the output string if successful, negative on @@ -115,94 +109,113 @@ int pkcs1_cryptencode(const void *msg, size_t msz, void *buf, size_t sz, * in PKCS#1 v. 2.0 (RFC2437). */ -int pkcs1_cryptdecode(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 pkcs1_cryptdecode(mp *m, octet *b, size_t sz, + unsigned long nbits, void *p) { pkcs1 *pp = p; const octet *q, *qq; size_t n, i; + int bad = 0; /* --- Check the size of the block looks sane --- */ - if (pp->epsz + 11 > sz) + if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */ return (-1); - q = buf; + mp_storeb(m, b, sz); + q = b; qq = q + sz; /* --- Ensure that the block looks OK --- */ - if (*q++ != 0 || *q++ != 2) - return (-1); + bad |= (*q++ != 0x00 || *q++ != 0x02); /* --- Check the nonzero padding --- */ i = 0; while (*q != 0 && q < qq) i++, q++; - if (i < 8 || qq - q < pp->epsz + 1) - return (-1); + bad |= (i < 8 || qq - q < pp->epsz + 1); q++; /* --- Check the encoding parameters --- */ - if (memcmp(q, pp->ep, pp->epsz) != 0) - return (-1); + bad |= (pp->ep && !memeq(bad ? b : q, pp->ep, pp->epsz)); q += pp->epsz; /* --- Done --- */ n = qq - q; - dstr_putm(d, q, n); - return (n); + memmove(b, bad ? b + 1 : q, n); + return (bad ? -1 : n); } /* --- @pkcs1_sigencode@ --- * * - * 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 PKCS1 parameter block * - * Returns: Zero if all went well, negative on failure. + * Returns: The encoded message representative, or null. * * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined * in PKCS#1 v. 2.0 (RFC2437). */ -int pkcs1_sigencode(const void *msg, size_t msz, void *buf, size_t sz, - void *p) +mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) { pkcs1 *pp = p; - octet *q, *qq; + octet *q; size_t n; /* --- Ensure that the buffer is sensibly sized --- */ if (pp->epsz + msz + 11 > sz) - return (-1); + return (0); /* --- Fill in the buffer --- */ - q = buf; - qq = q + sz; - *q++ = 0; - *q++ = 1; + q = b; + *q++ = 0x00; + *q++ = 0x01; n = sz - msz - pp->epsz - 3; memset(q, 0xff, n); q += n; *q++ = 0; - memcpy(q, pp->ep, pp->epsz); - q += pp->epsz; - memcpy(q, msg, msz); - return (0); + if (pp->ep) { + memcpy(q, pp->ep, pp->epsz); + q += pp->epsz; + } + memcpy(q, m, msz); + q += msz; + assert(q == b + sz); + return (mp_loadb(d, b, sz)); } /* --- @pkcs1_sigdecode@ --- * * - * Arguments: @const void *buf@ = pointer to encoded buffer - * @size_t sz@ = size of the encoded buffer - * @dstr *d@ = pointer to destination string - * @void *p@ = pointer to PKCS1 parameter block + * Arguments: @mp *s@ = the message representative + * @const void *m@ = the original message, or null (ignored) + * @size_t msz@ = the message size (ignored) + * @octet *b@ = a scratch buffer + * @size_t sz@ = size of the buffer (large enough) + * @unsigned long nbits@ = number of bits in @n@ + * @void *p@ = pointer to PKCS1 parameters * * Returns: The length of the output string if successful, negative on * failure. @@ -211,7 +224,8 @@ int pkcs1_sigencode(const void *msg, size_t msz, void *buf, size_t sz, * in PKCS#1 v. 2.0 (RFC2437). */ -int pkcs1_sigdecode(const void *buf, size_t sz, dstr *d, void *p) +int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz, + unsigned long nbits, void *p) { pkcs1 *pp = p; const octet *q, *qq; @@ -221,12 +235,13 @@ int pkcs1_sigdecode(const void *buf, size_t sz, dstr *d, void *p) if (pp->epsz + 10 > sz) return (-1); - q = buf; + mp_storeb(s, b, sz); + q = b; qq = q + sz; /* --- Ensure that the block looks OK --- */ - if (*q++ != 0 || *q++ != 1) + if (*q++ != 0x00 || *q++ != 0x01) return (-1); /* --- Check the padding --- */ @@ -239,14 +254,14 @@ int pkcs1_sigdecode(const void *buf, size_t sz, dstr *d, void *p) /* --- Check the encoding parameters --- */ - if (memcmp(q, pp->ep, pp->epsz) != 0) + if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0) return (-1); q += pp->epsz; /* --- Done --- */ n = qq - q; - dstr_putm(d, q, n); + memmove(b, q, n); return (n); }