Add an internal-representation no-op function.
[u/mdw/catacomb] / pss.c
CommitLineData
c080c887 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
63ghash *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
90int 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
143int 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
195fail:
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
211ghash *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
228void 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 -------------------------------------------------*/