chiark / gitweb /
Version bump.
[catacomb] / oaep.c
1 /* -*-c-*-
2  *
3  * $Id: oaep.c,v 1.1 2000/07/01 11:18:30 mdw Exp $
4  *
5  * Optimal asymmetric encryption packing
6  *
7  * (c) 2000 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Catacomb.
13  *
14  * Catacomb is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  * 
19  * Catacomb is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  * 
24  * You should have received a copy of the GNU Library General Public
25  * License along with Catacomb; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: oaep.c,v $
33  * Revision 1.1  2000/07/01 11:18:30  mdw
34  * Support for Optimal Asymmetric Encryption Padding.
35  *
36  */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <string.h>
41
42 #include <mLib/alloc.h>
43 #include <mLib/bits.h>
44 #include <mLib/dstr.h>
45
46 #include "gcipher.h"
47 #include "ghash.h"
48 #include "grand.h"
49 #include "oaep.h"
50
51 /*----- Main code ---------------------------------------------------------*/
52
53 /* --- @oaep_encode@ --- *
54  *
55  * Arguments:   @const void *msg@ = pointer to message data
56  *              @size_t msz@ = size of message data
57  *              @void *buf@ = pointer to output buffer
58  *              @size_t sz@ = size of the output buffer
59  *              @void *p@ = pointer to OAEP parameter block
60  *
61  * Returns:     Zero if all went well, negative on failure.
62  *
63  * Use:         Implements the operation @EME-OAEP-ENCODE@, as defined in
64  *              PKCS#1 v. 2.0 (RFC2437).
65  */
66
67 int oaep_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p)
68 {
69   oaep *o = p;
70   size_t hsz = o->ch->hashsz;
71   ghash *h = o->ch->init();
72   octet *q, *mq, *qq;
73   octet *pp;
74   gcipher *c;
75   size_t n;
76
77   /* --- Ensure that everything is sensibly sized --- */
78
79   if (2 * hsz + 2 + msz > sz)
80     return (-1);
81
82   /* --- Make the `seed' value --- */
83
84   q = buf;
85   *q++ = 0; sz--;
86   mq = q + hsz;
87   qq = q + sz;
88   o->r->ops->fill(o->r, q, hsz);
89
90   /* --- Fill in the rest of the buffer --- */
91
92   h->ops->hash(h, o->ep, o->epsz);
93   h->ops->done(h, mq);
94   h->ops->destroy(h);
95   pp = mq + hsz;
96   n = sz - 2 * hsz - msz - 1;
97   memset(pp, 0, n);
98   pp += n;
99   *pp++ = 1;
100   memcpy(pp, msg, msz);
101
102   /* --- Do the packing --- */
103
104   n = sz - hsz;
105   c = o->cc->init(q, hsz);
106   c->ops->encrypt(c, mq, mq, n);
107   c->ops->destroy(c);
108
109   c = o->cc->init(mq, n);
110   c->ops->encrypt(c, q, q, hsz);
111   c->ops->destroy(c);
112
113   /* --- Done --- */
114
115   return (0);
116 }
117
118 /* --- @oaep_decode@ --- *
119  *
120  * Arguments:   @const void *buf@ = pointer to encoded buffer
121  *              @size_t sz@ = size of the encoded buffer
122  *              @dstr *d@ = pointer to destination string
123  *              @void *p@ = pointer to OAEP parameter block
124  *
125  * Returns:     The length of the output string if successful, negative on
126  *              failure.
127  *
128  * Use:         Implements the operation @EME-OAEP-DECODE@, as defined in
129  *              PKCS#1 v. 2.0 (RFC2437).
130  */
131
132 int oaep_decode(const void *buf, size_t sz, dstr *d, void *p)
133 {
134   oaep *o = p;
135   gcipher *c;
136   ghash *h;
137   octet *q, *mq, *qq;
138   octet *pp;
139   size_t n;
140   size_t hsz = o->ch->hashsz;
141   int rc = -1;
142
143   /* --- Ensure that the block is large enough --- */
144
145   if (sz < 2 * hsz)
146     return (-1);
147
148   q = x_alloc(d->a, sz);
149   memcpy(q, buf, sz);
150
151   /* --- Decrypt the message --- */
152
153   if (*q != 0)
154     goto fail;
155   q++; sz--;
156   mq = q + hsz;
157   qq = q + sz;
158   n = sz - hsz;
159   c = o->cc->init(mq, n);
160   c->ops->decrypt(c, q, q, hsz);
161   c->ops->destroy(c);
162
163   c = o->cc->init(q, hsz);
164   c->ops->decrypt(c, mq, mq, n);
165   c->ops->destroy(c);
166   q--;
167
168   /* --- Check the hash on the encoding parameters --- */
169
170   h = o->ch->init();
171   h->ops->hash(h, o->ep, o->epsz);
172   h->ops->done(h, q);
173   if (memcmp(q, mq, hsz) != 0)
174     goto fail;
175
176   /* --- Now find the start of the actual message --- */
177
178   pp = mq + hsz;
179   while (*pp == 0 && pp < qq)
180     pp++;
181   if (pp >= qq || *pp++ != 1)
182     return (-1);
183   n = qq - pp;
184   dstr_putm(d, pp, n);
185   rc = n;
186
187 fail:
188   x_free(d->a, q);
189   return (rc);
190 }
191
192 /*----- That's all, folks -------------------------------------------------*/