progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / pub / pkcs1.c
CommitLineData
cd6c3eeb 1/* -*-c-*-
2 *
cd6c3eeb 3 * PKCS#1 1.5 packing
4 *
5 * (c) 2000 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
cd6c3eeb 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.
45c0fd36 16 *
cd6c3eeb 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.
45c0fd36 21 *
cd6c3eeb 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
cd6c3eeb 28/*----- Header files ------------------------------------------------------*/
29
30#include <string.h>
31
32#include <mLib/bits.h>
33#include <mLib/dstr.h>
141c1284 34#include <mLib/macros.h>
cd6c3eeb 35
52f339e9 36#include "ct.h"
cd6c3eeb 37#include "grand.h"
b817bfc6 38#include "rsa.h"
cd6c3eeb 39
40/*----- Main code ---------------------------------------------------------*/
41
42/* --- @pkcs1_cryptencode@ --- *
43 *
b817bfc6 44 * Arguments: @mp *d@ = where to put the answer
45 * @const void *m@ = pointer to message data
cd6c3eeb 46 * @size_t msz@ = size of message data
b817bfc6 47 * @octet *b@ = spare buffer
48 * @size_t sz@ = size of the buffer (big enough)
49 * @unsigned long nbits@ = length of bits of @n@
cd6c3eeb 50 * @void *p@ = pointer to PKCS1 parameter block
51 *
b817bfc6 52 * Returns: The encoded result, or null.
cd6c3eeb 53 *
54 * Use: Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined
55 * in PKCS#1 v. 2.0 (RFC2437).
56 */
57
b817bfc6 58mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
59 unsigned long nbits, void *p)
cd6c3eeb 60{
61 pkcs1 *pp = p;
62 grand *r = pp->r;
b817bfc6 63 octet *q;
cd6c3eeb 64 size_t i, n;
65
66 /* --- Ensure that the buffer is sensibly sized --- */
67
68 if (pp->epsz + msz + 11 > sz)
b817bfc6 69 return (0);
cd6c3eeb 70
b817bfc6 71 /* --- Allocate the buffer and fill it in --- */
cd6c3eeb 72
b817bfc6 73 q = b;
74 *q++ = 0x00;
75 *q++ = 0x02;
cd6c3eeb 76 n = sz - msz - pp->epsz - 3;
b817bfc6 77 GR_FILL(r, q, n);
cd6c3eeb 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;
b817bfc6 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 --- */
45c0fd36 93
b817bfc6 94 return (mp_loadb(d, b, sz));
cd6c3eeb 95}
96
97/* --- @pkcs1_cryptdecode@ --- *
98 *
b817bfc6 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@
cd6c3eeb 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
b817bfc6 112int pkcs1_cryptdecode(mp *m, octet *b, size_t sz,
113 unsigned long nbits, void *p)
cd6c3eeb 114{
115 pkcs1 *pp = p;
116 const octet *q, *qq;
117 size_t n, i;
52f339e9 118 uint32 goodp = 1;
cd6c3eeb 119
120 /* --- Check the size of the block looks sane --- */
121
b817bfc6 122 if (pp->epsz + 11 > sz) /* OK: independent of ciphertext */
cd6c3eeb 123 return (-1);
b817bfc6 124 mp_storeb(m, b, sz);
125 q = b;
7629bca8 126 qq = q + sz;
cd6c3eeb 127
128 /* --- Ensure that the block looks OK --- */
129
52f339e9
MW
130 goodp &= ct_inteq(*q++, 0);
131 goodp &= ct_inteq(*q++, 2);
cd6c3eeb 132
133 /* --- Check the nonzero padding --- */
134
135 i = 0;
136 while (*q != 0 && q < qq)
137 i++, q++;
52f339e9
MW
138 goodp &= ct_intle(8, i);
139 goodp &= ~ct_intle(qq - q, pp->epsz + 1);
cd6c3eeb 140 q++;
141
142 /* --- Check the encoding parameters --- */
143
52f339e9
MW
144 if (pp->ep)
145 goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz);
cd6c3eeb 146 q += pp->epsz;
147
148 /* --- Done --- */
149
150 n = qq - q;
52f339e9
MW
151 memmove(b, b + ct_pick(goodp, 1, q - b), n);
152 return (goodp ? n : -1);
cd6c3eeb 153}
154
155/* --- @pkcs1_sigencode@ --- *
156 *
b817bfc6 157 * Arguments: @mp *d@ = where to put the answer
158 * @const void *m@ = pointer to message data
cd6c3eeb 159 * @size_t msz@ = size of message data
b817bfc6 160 * @octet *b@ = spare buffer
161 * @size_t sz@ = size of the buffer (big enough)
162 * @unsigned long nbits@ = length of bits of @n@
cd6c3eeb 163 * @void *p@ = pointer to PKCS1 parameter block
164 *
b817bfc6 165 * Returns: The encoded message representative, or null.
cd6c3eeb 166 *
167 * Use: Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined
168 * in PKCS#1 v. 2.0 (RFC2437).
169 */
170
b817bfc6 171mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
172 unsigned long nbits, void *p)
cd6c3eeb 173{
174 pkcs1 *pp = p;
b817bfc6 175 octet *q;
cd6c3eeb 176 size_t n;
177
178 /* --- Ensure that the buffer is sensibly sized --- */
179
180 if (pp->epsz + msz + 11 > sz)
b817bfc6 181 return (0);
cd6c3eeb 182
183 /* --- Fill in the buffer --- */
184
b817bfc6 185 q = b;
186 *q++ = 0x00;
187 *q++ = 0x01;
cd6c3eeb 188 n = sz - msz - pp->epsz - 3;
189 memset(q, 0xff, n);
190 q += n;
191 *q++ = 0;
b817bfc6 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));
cd6c3eeb 200}
201
202/* --- @pkcs1_sigdecode@ --- *
203 *
b817bfc6 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
cd6c3eeb 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
b817bfc6 219int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz,
220 unsigned long nbits, void *p)
cd6c3eeb 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);
b817bfc6 230 mp_storeb(s, b, sz);
231 q = b;
7629bca8 232 qq = q + sz;
cd6c3eeb 233
234 /* --- Ensure that the block looks OK --- */
235
b817bfc6 236 if (*q++ != 0x00 || *q++ != 0x01)
cd6c3eeb 237 return (-1);
238
239 /* --- Check the padding --- */
240
241 i = 0;
242 while (*q == 0xff && q < qq)
243 i++, q++;
0586d2a1 244 if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0)
cd6c3eeb 245 return (-1);
cd6c3eeb 246
247 /* --- Check the encoding parameters --- */
248
141c1284 249 if (pp->ep && MEMCMP(q, !=, pp->ep, pp->epsz))
cd6c3eeb 250 return (-1);
251 q += pp->epsz;
252
253 /* --- Done --- */
254
255 n = qq - q;
b817bfc6 256 memmove(b, q, n);
cd6c3eeb 257 return (n);
258}
259
260/*----- That's all, folks -------------------------------------------------*/