root/trunk/src/libopensc/padding.c

Revision 3115, 8.5 KB (checked in by nils, 22 months ago)

implement support for SHA2 (still experimental)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * padding.c: miscellaneous padding functions
3 *
4 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
5 * Copyright (C) 2003 - 2007  Nils Larsch <larsch@trustcenter.de>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21
22#include "internal.h"
23#include <string.h>
24#include <stdlib.h>
25
26/* TODO doxygen comments */
27
28/*
29 * Prefixes for pkcs-v1 signatures
30 */
31static const u8 hdr_md5[] = {
32        0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
33        0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
34};
35static const u8 hdr_sha1[] = {
36        0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
37        0x05, 0x00, 0x04, 0x14
38};
39static const u8 hdr_sha256[] = {
40        0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
41        0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
42};
43static const u8 hdr_sha384[] = {
44        0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
45        0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
46};
47static const u8 hdr_sha512[] = {
48        0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
49        0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
50};
51static const u8 hdr_sha224[] = {
52        0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
53        0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
54};
55static const u8 hdr_ripemd160[] = {
56        0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01,
57        0x05, 0x00, 0x04, 0x14
58};
59
60
61static const struct digest_info_prefix {
62        unsigned int    algorithm;
63        const u8 *      hdr;
64        size_t          hdr_len;
65        size_t          hash_len;
66} digest_info_prefix[] = {
67      { SC_ALGORITHM_RSA_HASH_NONE,     NULL,           0,                      0      },
68      { SC_ALGORITHM_RSA_HASH_MD5,      hdr_md5,        sizeof(hdr_md5),        16      },
69      { SC_ALGORITHM_RSA_HASH_SHA1,     hdr_sha1,       sizeof(hdr_sha1),       20      },
70      { SC_ALGORITHM_RSA_HASH_SHA256,   hdr_sha256,     sizeof(hdr_sha256),     32      },
71      { SC_ALGORITHM_RSA_HASH_SHA384,   hdr_sha384,     sizeof(hdr_sha384),     48      },
72      { SC_ALGORITHM_RSA_HASH_SHA512,   hdr_sha512,     sizeof(hdr_sha512),     64      },
73      { SC_ALGORITHM_RSA_HASH_SHA224,   hdr_sha224,     sizeof(hdr_sha224),     28      },
74      { SC_ALGORITHM_RSA_HASH_RIPEMD160,hdr_ripemd160,  sizeof(hdr_ripemd160),  20      },
75      { SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL,           0,                      36      },
76      { 0,                              NULL,           0,                      0       }
77};
78
79/* add/remove pkcs1 BT01 padding */
80
81static int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len,
82        u8 *out, size_t *out_len, size_t mod_length)
83{
84        size_t i;
85
86        if (*out_len < mod_length)
87                return SC_ERROR_BUFFER_TOO_SMALL;
88        if (in_len + 11 > mod_length)
89                return SC_ERROR_INVALID_ARGUMENTS;
90        i = mod_length - in_len;
91        memmove(out + i, in, in_len);
92        *out++ = 0x00;
93        *out++ = 0x01;
94       
95        memset(out, 0xFF, i - 3);
96        out += i - 3;
97        *out = 0x00;
98
99        *out_len = mod_length;
100        return SC_SUCCESS;
101}
102
103int sc_pkcs1_strip_01_padding(const u8 *in_dat, size_t in_len,
104        u8 *out, size_t *out_len)
105{
106        const u8 *tmp = in_dat;
107        size_t    len;
108
109        if (in_dat == NULL || in_len < 10)
110                return SC_ERROR_INTERNAL;
111        /* skip leading zero byte */
112        if (*tmp == 0) {
113                tmp++;
114                in_len--;
115        }
116        len = in_len;
117        if (*tmp != 0x01)
118                return SC_ERROR_WRONG_PADDING;
119        for (tmp++, len--; *tmp == 0xff && len != 0; tmp++, len--)
120                ;
121        if (!len || (in_len - len) < 9 || *tmp++ != 0x00)
122                return SC_ERROR_WRONG_PADDING;
123        len--;
124        if (out == NULL)
125                /* just check the padding */
126                return SC_SUCCESS;
127        if (*out_len < len)
128                return SC_ERROR_INTERNAL;
129        memmove(out, tmp, len);
130        *out_len = len;
131        return SC_SUCCESS;
132}
133
134/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
135 * needed/implemented) */
136int sc_pkcs1_strip_02_padding(const u8 *data, size_t len, u8 *out,
137        size_t *out_len)
138{
139        unsigned int    n = 0;
140
141        if (data == NULL || len < 3)
142                return SC_ERROR_INTERNAL;
143        /* skip leading zero byte */
144        if (*data == 0) {
145                data++;
146                len--;
147        }
148        if (data[0] != 0x02)
149                return SC_ERROR_WRONG_PADDING;
150        /* skip over padding bytes */
151        for (n = 1; n < len && data[n]; n++)
152                ;
153        /* Must be at least 8 pad bytes */
154        if (n >= len || n < 9)
155                return SC_ERROR_WRONG_PADDING;
156        n++;
157        if (out == NULL)
158                /* just check the padding */
159                return SC_SUCCESS;
160        /* Now move decrypted contents to head of buffer */
161        if (*out_len < len -  n)
162                return SC_ERROR_INTERNAL;
163        memmove(out, data + n, len - n);
164        return len - n;
165}
166
167/* add/remove DigestInfo prefix */
168static int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm,
169        const u8 *in, size_t in_len, u8 *out, size_t *out_len)
170{
171        int i;
172
173        for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
174                if (algorithm == digest_info_prefix[i].algorithm) {
175                        const u8 *hdr      = digest_info_prefix[i].hdr;
176                        size_t    hdr_len  = digest_info_prefix[i].hdr_len,
177                                  hash_len = digest_info_prefix[i].hash_len;
178                        if (in_len != hash_len ||
179                            *out_len < (hdr_len + hash_len))
180                                return SC_ERROR_INTERNAL;
181                        memmove(out + hdr_len, in, hash_len);
182                        memmove(out, hdr, hdr_len);
183                        *out_len = hdr_len + hash_len;
184                        return SC_SUCCESS;
185                }
186        }
187
188        return SC_ERROR_INTERNAL;
189}
190
191int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
192        const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len)
193{
194        int i;
195
196        for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
197                size_t    hdr_len  = digest_info_prefix[i].hdr_len,
198                          hash_len = digest_info_prefix[i].hash_len;
199                const u8 *hdr      = digest_info_prefix[i].hdr;
200               
201                if (in_len == (hdr_len + hash_len) &&
202                    !memcmp(in_dat, hdr, hdr_len)) {
203                        if (algorithm)
204                                *algorithm = digest_info_prefix[i].algorithm;
205                        if (out_dat == NULL)
206                                /* just check the DigestInfo prefix */
207                                return SC_SUCCESS;
208                        if (*out_len < hash_len)
209                                return SC_ERROR_INTERNAL;
210                        memmove(out_dat, in_dat + hdr_len, hash_len);
211                        *out_len = hash_len;
212                        return SC_SUCCESS;
213                }
214        }
215        return SC_ERROR_INTERNAL;
216}
217
218/* general PKCS#1 encoding function */
219int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
220        const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len)
221{
222        int    i;
223        size_t tmp_len = *out_len;
224        const u8    *tmp = in;
225        unsigned int hash_algo, pad_algo;
226
227        hash_algo = flags & (SC_ALGORITHM_RSA_HASHES | SC_ALGORITHM_RSA_HASH_NONE);
228        pad_algo  = flags & SC_ALGORITHM_RSA_PADS;
229
230        if (hash_algo != SC_ALGORITHM_RSA_HASH_NONE) {
231                i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len,
232                                                    out, &tmp_len);
233                if (i != SC_SUCCESS) {
234                        sc_error(ctx, "Unable to add digest info 0x%x\n",
235                              hash_algo);
236                        return i;
237                }
238                tmp = out;
239        } else
240                tmp_len = in_len;
241
242        switch(pad_algo) {
243        case SC_ALGORITHM_RSA_PAD_NONE:
244                /* padding done by card => nothing to do */
245                if (out != tmp)
246                        memcpy(out, tmp, tmp_len);
247                *out_len = tmp_len;
248                return SC_SUCCESS;
249        case SC_ALGORITHM_RSA_PAD_PKCS1:
250                /* add pkcs1 bt01 padding */
251                return sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len,
252                                               mod_len);
253        default:
254                /* currently only pkcs1 padding is supported */
255                sc_error(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo);
256                return SC_ERROR_NOT_SUPPORTED;
257        }
258}
259
260int sc_get_encoding_flags(sc_context_t *ctx,
261        unsigned long iflags, unsigned long caps,
262        unsigned long *pflags, unsigned long *sflags)
263{
264        size_t i;
265
266        if (pflags == NULL || sflags == NULL)
267                return SC_ERROR_INVALID_ARGUMENTS;
268
269        for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
270                if (iflags & digest_info_prefix[i].algorithm) {
271                        if (digest_info_prefix[i].algorithm != SC_ALGORITHM_RSA_HASH_NONE &&
272                            caps & digest_info_prefix[i].algorithm)
273                                *sflags |= digest_info_prefix[i].algorithm;
274                        else
275                                *pflags |= digest_info_prefix[i].algorithm;
276                        break;
277                }
278        }
279
280        if (iflags & SC_ALGORITHM_RSA_PAD_PKCS1) {
281                if (caps & SC_ALGORITHM_RSA_PAD_PKCS1)
282                        *sflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
283                else
284                        *pflags |= SC_ALGORITHM_RSA_PAD_PKCS1;
285        } else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
286                if (!(caps & SC_ALGORITHM_RSA_RAW)) {
287                        sc_error(ctx, "raw RSA is not supported");
288                        return SC_ERROR_NOT_SUPPORTED;
289                }
290                *sflags |= SC_ALGORITHM_RSA_RAW;
291                /* in case of raw RSA there is nothing to pad */
292                *pflags = 0;
293        } else {
294                sc_error(ctx, "unsupported algorithm");
295                return SC_ERROR_NOT_SUPPORTED;
296        }
297
298        return SC_SUCCESS;
299}
Note: See TracBrowser for help on using the browser.