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