configure.ac: Replace with a new version.
[u/mdw/catacomb] / pkcs1.c
1 /* -*-c-*-
2 *
3 * $Id: pkcs1.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
4 *
5 * PKCS#1 1.5 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 /*----- Header files ------------------------------------------------------*/
31
32 #include <string.h>
33
34 #include <mLib/bits.h>
35 #include <mLib/dstr.h>
36
37 #include "ct.h"
38 #include "grand.h"
39 #include "rsa.h"
40
41 /*----- Main code ---------------------------------------------------------*/
42
43 /* --- @pkcs1_cryptencode@ --- *
44 *
45 * Arguments: @mp *d@ = where to put the answer
46 * @const void *m@ = pointer to message data
47 * @size_t msz@ = size of message data
48 * @octet *b@ = spare buffer
49 * @size_t sz@ = size of the buffer (big enough)
50 * @unsigned long nbits@ = length of bits of @n@
51 * @void *p@ = pointer to PKCS1 parameter block
52 *
53 * Returns: The encoded result, or null.
54 *
55 * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined
56 * in PKCS#1 v. 2.0 (RFC2437).
57 */
58
59 mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
60 unsigned long nbits, void *p)
61 {
62 pkcs1 *pp = p;
63 grand *r = pp->r;
64 octet *q;
65 size_t i, n;
66
67 /* --- Ensure that the buffer is sensibly sized --- */
68
69 if (pp->epsz + msz + 11 > sz)
70 return (0);
71
72 /* --- Allocate the buffer and fill it in --- */
73
74 q = b;
75 *q++ = 0x00;
76 *q++ = 0x02;
77 n = sz - msz - pp->epsz - 3;
78 GR_FILL(r, q, n);
79 for (i = 0; i < n; i++) {
80 if (*q == 0)
81 *q = r->ops->range(r, 255) + 1;
82 q++;
83 }
84 *q++ = 0;
85 if (pp->ep) {
86 memcpy(q, pp->ep, pp->epsz);
87 q += pp->epsz;
88 }
89 memcpy(q, m, msz);
90 q += msz;
91 assert(q == b + sz);
92
93 /* --- Collect the result --- */
94
95 return (mp_loadb(d, b, sz));
96 }
97
98 /* --- @pkcs1_cryptdecode@ --- *
99 *
100 * Arguments: @mp *m@ = the decrypted message
101 * @octet *b@ = pointer to a buffer to work in
102 * @size_t sz@ = the size of the buffer (big enough)
103 * @unsigned long nbits@ = the number of bits in @n@
104 * @void *p@ = pointer to PKCS1 parameter block
105 *
106 * Returns: The length of the output string if successful, negative on
107 * failure.
108 *
109 * Use: Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined
110 * in PKCS#1 v. 2.0 (RFC2437).
111 */
112
113 int pkcs1_cryptdecode(mp *m, octet *b, size_t sz,
114 unsigned long nbits, void *p)
115 {
116 pkcs1 *pp = p;
117 const octet *q, *qq;
118 size_t n, i;
119 uint32 goodp = 1;
120
121 /* --- Check the size of the block looks sane --- */
122
123 if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */
124 return (-1);
125 mp_storeb(m, b, sz);
126 q = b;
127 qq = q + sz;
128
129 /* --- Ensure that the block looks OK --- */
130
131 goodp &= ct_inteq(*q++, 0);
132 goodp &= ct_inteq(*q++, 2);
133
134 /* --- Check the nonzero padding --- */
135
136 i = 0;
137 while (*q != 0 && q < qq)
138 i++, q++;
139 goodp &= ct_intle(8, i);
140 goodp &= ~ct_intle(qq - q, pp->epsz + 1);
141 q++;
142
143 /* --- Check the encoding parameters --- */
144
145 if (pp->ep)
146 goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz);
147 q += pp->epsz;
148
149 /* --- Done --- */
150
151 n = qq - q;
152 memmove(b, b + ct_pick(goodp, 1, q - b), n);
153 return (goodp ? n : -1);
154 }
155
156 /* --- @pkcs1_sigencode@ --- *
157 *
158 * Arguments: @mp *d@ = where to put the answer
159 * @const void *m@ = pointer to message data
160 * @size_t msz@ = size of message data
161 * @octet *b@ = spare buffer
162 * @size_t sz@ = size of the buffer (big enough)
163 * @unsigned long nbits@ = length of bits of @n@
164 * @void *p@ = pointer to PKCS1 parameter block
165 *
166 * Returns: The encoded message representative, or null.
167 *
168 * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined
169 * in PKCS#1 v. 2.0 (RFC2437).
170 */
171
172 mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
173 unsigned long nbits, void *p)
174 {
175 pkcs1 *pp = p;
176 octet *q;
177 size_t n;
178
179 /* --- Ensure that the buffer is sensibly sized --- */
180
181 if (pp->epsz + msz + 11 > sz)
182 return (0);
183
184 /* --- Fill in the buffer --- */
185
186 q = b;
187 *q++ = 0x00;
188 *q++ = 0x01;
189 n = sz - msz - pp->epsz - 3;
190 memset(q, 0xff, n);
191 q += n;
192 *q++ = 0;
193 if (pp->ep) {
194 memcpy(q, pp->ep, pp->epsz);
195 q += pp->epsz;
196 }
197 memcpy(q, m, msz);
198 q += msz;
199 assert(q == b + sz);
200 return (mp_loadb(d, b, sz));
201 }
202
203 /* --- @pkcs1_sigdecode@ --- *
204 *
205 * Arguments: @mp *s@ = the message representative
206 * @const void *m@ = the original message, or null (ignored)
207 * @size_t msz@ = the message size (ignored)
208 * @octet *b@ = a scratch buffer
209 * @size_t sz@ = size of the buffer (large enough)
210 * @unsigned long nbits@ = number of bits in @n@
211 * @void *p@ = pointer to PKCS1 parameters
212 *
213 * Returns: The length of the output string if successful, negative on
214 * failure.
215 *
216 * Use: Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined
217 * in PKCS#1 v. 2.0 (RFC2437).
218 */
219
220 int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz,
221 unsigned long nbits, void *p)
222 {
223 pkcs1 *pp = p;
224 const octet *q, *qq;
225 size_t i, n;
226
227 /* --- Check the size of the block looks sane --- */
228
229 if (pp->epsz + 10 > sz)
230 return (-1);
231 mp_storeb(s, b, sz);
232 q = b;
233 qq = q + sz;
234
235 /* --- Ensure that the block looks OK --- */
236
237 if (*q++ != 0x00 || *q++ != 0x01)
238 return (-1);
239
240 /* --- Check the padding --- */
241
242 i = 0;
243 while (*q == 0xff && q < qq)
244 i++, q++;
245 if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0)
246 return (-1);
247
248 /* --- Check the encoding parameters --- */
249
250 if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0)
251 return (-1);
252 q += pp->epsz;
253
254 /* --- Done --- */
255
256 n = qq - q;
257 memmove(b, q, n);
258 return (n);
259 }
260
261 /*----- That's all, folks -------------------------------------------------*/