chiark / gitweb /
Add some more vectors, and a whinge about how Skipjack test vectors are.
[catacomb] / pss.c
1 /* -*-c-*-
2  *
3  * $Id: pss.c,v 1.1 2000/07/20 20:13:38 mdw Exp $
4  *
5  * Probabistic signature scheme
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: pss.c,v $
33  * Revision 1.1  2000/07/20 20:13:38  mdw
34  * Added Bellare and Rogaway's PSS encoding for RSA signatures.
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 "pss.h"
50
51 /*----- Main code ---------------------------------------------------------*/
52
53 /* --- @pss_presign@ --- *
54  *
55  * Arguments:   @pss *pp@ = pointer to PSS parameter block
56  *
57  * Returns:     An initialized generic hash context.
58  *
59  * Use:         Initializes a hash function for signing with PSS.  A salt is
60  *              chosen and written into the parameter block.
61  */
62
63 ghash *pss_presign(pss *pp)
64 {
65   size_t hsz = pp->ch->hashsz;
66   octet *salt = xmalloc(hsz);
67   ghash *h;
68
69   pp->r->ops->fill(pp->r, salt, hsz);
70   pp->salt = salt;
71   h = pp->ch->init();
72   h->ops->hash(h, salt, hsz);
73   return (h);
74 }
75
76 /* --- @pss_encode@ --- *
77  *
78  * Arguments:   @const void *msg@ = pointer to message (hash) data
79  *              @size_t msz@ = size of message data
80  *              @void *buf@ = pointer to output buffer
81  *              @size_t sz@ = size of the output buffer
82  *              @void *p@ = pointer to PSS parameter block
83  *
84  * Returns:     Zero of all went well, negative on failure.
85  *
86  * Use:         Implements the operation @EMSA-PSS-ENCODE@, as defined in
87  *              PKCS#1 v. 2.1 draft 1.
88  */
89
90 int pss_encode(const void *msg, size_t msz, void *buf, size_t sz, void *p)
91 {
92   pss *pp = p;
93   octet *q, *mq, *qq;
94   gcipher *c;
95   size_t hsz = pp->ch->hashsz;
96   size_t n;
97
98   /* --- Ensure that everything is sensibly sized --- */
99
100   if (hsz + msz + 1 > sz)
101     return (-1);
102
103   /* --- Fill in the initial buffer --- */
104
105   q = buf;
106   *q++ = 0; sz--;
107   mq = q + msz;
108   qq = q + sz;
109   n = sz - msz;
110   memcpy(q, msg, msz);
111   if (pp->salt)
112     memcpy(mq, pp->salt, hsz);
113   else
114     memset(mq, 0, hsz);
115   memset(mq + hsz, 0, n - hsz);
116
117   /* --- Do the encryption --- */
118
119   c = pp->cc->init(msg, msz);
120   c->ops->encrypt(c, mq, mq, n);
121   c->ops->destroy(c);
122
123   /* --- Done --- */
124
125   return (0);
126 }
127
128 /* --- @pss_decode@ --- *
129  *
130  * Arguments:   @const void *buf@ = pointer to encoded buffer
131  *              @size_t sz@ = size of the encoded byffer
132  *              @dstr *d@ = pointer to destination string
133  *              @void *p@ = pointer to PSS parameter block
134  *
135  * Returns:     The length of the output string (hash) if successful,
136  *              negative on failure.
137  *
138  * Use:         Implements most of the operation @EMSA_PSS_VERIFY@, as
139  *              defined in PCSK#1 v. 2.1 draft 1.  The salt value is filled
140  *              in ready for hashing of the data to start.
141  */
142
143 int pss_decode(const void *buf, size_t sz, dstr *d, void *p)
144 {
145   pss *pp = p;
146   gcipher *c;
147   octet *q, *mq, *qq;
148   octet *ppp;
149   size_t n;
150   size_t hsz = pp->ch->hashsz;
151   int rc = -1;
152
153   /* --- Ensure that the block is large enough --- */
154
155   if (sz < 2 * hsz + 1)
156     return (-1);
157
158   q = x_alloc(d->a, sz);
159   memcpy(q, buf, sz);
160
161   /* --- Recover the salt --- */
162
163   if (*q++ != 0)
164     goto fail;
165   sz--;
166   mq = q + hsz;
167   qq = q + sz;
168   n = sz - hsz;
169   c = pp->cc->init(q, hsz);
170   c->ops->decrypt(c, mq, mq, n);
171   c->ops->destroy(c);
172
173   /* --- Now check the recovery --- */
174
175   ppp = mq + hsz;
176   while (ppp < qq) {
177     if (*ppp)
178       goto fail;
179     ppp++;
180   }
181
182   /* --- Done --- */
183
184   if (pp->salt) {
185     if (memcmp(pp->salt, mq, hsz) != 0)
186       goto fail;
187   } else {
188     qq = xmalloc(hsz);
189     memcpy(qq, mq, hsz);
190     pp->salt = qq;
191   }
192   dstr_putm(d, q, hsz);
193   rc = hsz;
194
195 fail:
196   x_free(d->a, q - 1);
197   return (rc);
198 }
199
200 /* --- @pss_preverify@ --- *
201  *
202  * Arguments:   @pss *pp@ = pointer to PSS parameter block
203  *
204  * Returns:     An initialized generic hash context.
205  *
206  * Use:         Initializes a hash function for use with PSS.  A salt is
207  *              read from the parameter block, where @pss_decode@ should have
208  *              left it.
209  */
210
211 ghash *pss_preverify(pss *pp)
212 {
213   size_t hsz = pp->ch->hashsz;
214   ghash *h = pp->ch->init();
215   h->ops->hash(h, pp->salt, hsz);
216   return (h);
217 }
218
219 /* --- @pss_done@ --- *
220  *
221  * Arguments:   @pss *pp@ = pointer to PSS parameter block
222  *
223  * Returns:     ---
224  *
225  * Use:         Disposes of a PSS parameter block once it's finished with.
226  */
227
228 void pss_done(pss *pp)
229 {
230   if (pp->salt) {
231     xfree(pp->salt);
232     pp->salt = 0;
233   }
234 }
235
236 /*----- That's all, folks -------------------------------------------------*/