progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / pub / pkcs1.c
1 /* -*-c-*-
2 *
3 * PKCS#1 1.5 packing
4 *
5 * (c) 2000 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <string.h>
31
32 #include <mLib/bits.h>
33 #include <mLib/dstr.h>
34 #include <mLib/macros.h>
35
36 #include "ct.h"
37 #include "grand.h"
38 #include "rsa.h"
39
40 /*----- Main code ---------------------------------------------------------*/
41
42 /* --- @pkcs1_cryptencode@ --- *
43 *
44 * Arguments: @mp *d@ = where to put the answer
45 * @const void *m@ = pointer to message data
46 * @size_t msz@ = size of message data
47 * @octet *b@ = spare buffer
48 * @size_t sz@ = size of the buffer (big enough)
49 * @unsigned long nbits@ = length of bits of @n@
50 * @void *p@ = pointer to PKCS1 parameter block
51 *
52 * Returns: The encoded result, or null.
53 *
54 * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined
55 * in PKCS#1 v. 2.0 (RFC2437).
56 */
57
58 mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
59 unsigned long nbits, void *p)
60 {
61 pkcs1 *pp = p;
62 grand *r = pp->r;
63 octet *q;
64 size_t i, n;
65
66 /* --- Ensure that the buffer is sensibly sized --- */
67
68 if (pp->epsz + msz + 11 > sz)
69 return (0);
70
71 /* --- Allocate the buffer and fill it in --- */
72
73 q = b;
74 *q++ = 0x00;
75 *q++ = 0x02;
76 n = sz - msz - pp->epsz - 3;
77 GR_FILL(r, q, n);
78 for (i = 0; i < n; i++) {
79 if (*q == 0)
80 *q = r->ops->range(r, 255) + 1;
81 q++;
82 }
83 *q++ = 0;
84 if (pp->ep) {
85 memcpy(q, pp->ep, pp->epsz);
86 q += pp->epsz;
87 }
88 memcpy(q, m, msz);
89 q += msz;
90 assert(q == b + sz);
91
92 /* --- Collect the result --- */
93
94 return (mp_loadb(d, b, sz));
95 }
96
97 /* --- @pkcs1_cryptdecode@ --- *
98 *
99 * Arguments: @mp *m@ = the decrypted message
100 * @octet *b@ = pointer to a buffer to work in
101 * @size_t sz@ = the size of the buffer (big enough)
102 * @unsigned long nbits@ = the number of bits in @n@
103 * @void *p@ = pointer to PKCS1 parameter block
104 *
105 * Returns: The length of the output string if successful, negative on
106 * failure.
107 *
108 * Use: Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined
109 * in PKCS#1 v. 2.0 (RFC2437).
110 */
111
112 int pkcs1_cryptdecode(mp *m, octet *b, size_t sz,
113 unsigned long nbits, void *p)
114 {
115 pkcs1 *pp = p;
116 const octet *q, *qq;
117 size_t n, i;
118 uint32 goodp = 1;
119
120 /* --- Check the size of the block looks sane --- */
121
122 if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */
123 return (-1);
124 mp_storeb(m, b, sz);
125 q = b;
126 qq = q + sz;
127
128 /* --- Ensure that the block looks OK --- */
129
130 goodp &= ct_inteq(*q++, 0);
131 goodp &= ct_inteq(*q++, 2);
132
133 /* --- Check the nonzero padding --- */
134
135 i = 0;
136 while (*q != 0 && q < qq)
137 i++, q++;
138 goodp &= ct_intle(8, i);
139 goodp &= ~ct_intle(qq - q, pp->epsz + 1);
140 q++;
141
142 /* --- Check the encoding parameters --- */
143
144 if (pp->ep)
145 goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz);
146 q += pp->epsz;
147
148 /* --- Done --- */
149
150 n = qq - q;
151 memmove(b, b + ct_pick(goodp, 1, q - b), n);
152 return (goodp ? n : -1);
153 }
154
155 /* --- @pkcs1_sigencode@ --- *
156 *
157 * Arguments: @mp *d@ = where to put the answer
158 * @const void *m@ = pointer to message data
159 * @size_t msz@ = size of message data
160 * @octet *b@ = spare buffer
161 * @size_t sz@ = size of the buffer (big enough)
162 * @unsigned long nbits@ = length of bits of @n@
163 * @void *p@ = pointer to PKCS1 parameter block
164 *
165 * Returns: The encoded message representative, or null.
166 *
167 * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined
168 * in PKCS#1 v. 2.0 (RFC2437).
169 */
170
171 mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
172 unsigned long nbits, void *p)
173 {
174 pkcs1 *pp = p;
175 octet *q;
176 size_t n;
177
178 /* --- Ensure that the buffer is sensibly sized --- */
179
180 if (pp->epsz + msz + 11 > sz)
181 return (0);
182
183 /* --- Fill in the buffer --- */
184
185 q = b;
186 *q++ = 0x00;
187 *q++ = 0x01;
188 n = sz - msz - pp->epsz - 3;
189 memset(q, 0xff, n);
190 q += n;
191 *q++ = 0;
192 if (pp->ep) {
193 memcpy(q, pp->ep, pp->epsz);
194 q += pp->epsz;
195 }
196 memcpy(q, m, msz);
197 q += msz;
198 assert(q == b + sz);
199 return (mp_loadb(d, b, sz));
200 }
201
202 /* --- @pkcs1_sigdecode@ --- *
203 *
204 * Arguments: @mp *s@ = the message representative
205 * @const void *m@ = the original message, or null (ignored)
206 * @size_t msz@ = the message size (ignored)
207 * @octet *b@ = a scratch buffer
208 * @size_t sz@ = size of the buffer (large enough)
209 * @unsigned long nbits@ = number of bits in @n@
210 * @void *p@ = pointer to PKCS1 parameters
211 *
212 * Returns: The length of the output string if successful, negative on
213 * failure.
214 *
215 * Use: Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined
216 * in PKCS#1 v. 2.0 (RFC2437).
217 */
218
219 int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz,
220 unsigned long nbits, void *p)
221 {
222 pkcs1 *pp = p;
223 const octet *q, *qq;
224 size_t i, n;
225
226 /* --- Check the size of the block looks sane --- */
227
228 if (pp->epsz + 10 > sz)
229 return (-1);
230 mp_storeb(s, b, sz);
231 q = b;
232 qq = q + sz;
233
234 /* --- Ensure that the block looks OK --- */
235
236 if (*q++ != 0x00 || *q++ != 0x01)
237 return (-1);
238
239 /* --- Check the padding --- */
240
241 i = 0;
242 while (*q == 0xff && q < qq)
243 i++, q++;
244 if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0)
245 return (-1);
246
247 /* --- Check the encoding parameters --- */
248
249 if (pp->ep && MEMCMP(q, !=, pp->ep, pp->epsz))
250 return (-1);
251 q += pp->epsz;
252
253 /* --- Done --- */
254
255 n = qq - q;
256 memmove(b, q, n);
257 return (n);
258 }
259
260 /*----- That's all, folks -------------------------------------------------*/