/* -*-c-*-
*
- * $Id: pkcs1.c,v 1.2 2000/07/05 17:49:48 mdw Exp $
+ * $Id: pkcs1.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
*
* PKCS#1 1.5 packing
*
* MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: pkcs1.c,v $
- * 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 <string.h>
#include <mLib/dstr.h>
#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
* 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;
- qq = buf + sz;
+ 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.
* 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;
if (pp->epsz + 10 > sz)
return (-1);
- q = buf;
- qq = buf + sz;
+ 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 --- */
/* --- 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);
}