root/trunk/src/libopensc/pkcs15-algo.c

Revision 3304, 11.2 KB (checked in by ludovic.rousseau, 12 months ago)

add support of ruToken

Thanks to Andrew V. Stepanov for the patch
http://www.opensc-project.org/pipermail/opensc-devel/2007-December/010617.html

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * pkc15-algo.c: ASN.1 handling for algorithm IDs and parameters
3 *
4 * Copyright (C) 2001, 2002  Olaf Kirch <okir@lst.de>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "internal.h"
22#include "asn1.h"
23#include <stdio.h>
24#include <string.h>
25#include <ctype.h>
26#include <assert.h>
27#include <stdlib.h>
28
29/*
30 * AlgorithmIdentifier handling
31 */
32static struct sc_asn1_entry     c_asn1_des_iv[] = {
33        { "iv", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
34        { NULL, 0, 0, 0, NULL, NULL }
35};
36
37static int
38asn1_decode_des_params(sc_context_t *ctx, void **paramp,
39                                const u8 *buf, size_t buflen, int depth)
40{
41        struct sc_asn1_entry asn1_des_iv[2];
42        u8      iv[8];
43        int     ivlen = 8, r;
44
45        sc_copy_asn1_entry(c_asn1_des_iv, asn1_des_iv);
46        sc_format_asn1_entry(asn1_des_iv + 0, iv, &ivlen, 0);
47        r = _sc_asn1_decode(ctx, asn1_des_iv, buf, buflen, NULL, NULL, 0, depth + 1);
48        if (r < 0)
49                return r;
50        if (ivlen != 8)
51                return SC_ERROR_INVALID_ASN1_OBJECT;
52        *paramp = malloc(8);
53        if (!*paramp)
54                return SC_ERROR_OUT_OF_MEMORY;
55        memcpy(*paramp, iv, 8);
56        return 0;
57}
58
59static int
60asn1_encode_des_params(sc_context_t *ctx, void *params,
61                                u8 **buf, size_t *buflen, int depth)
62{
63        struct sc_asn1_entry asn1_des_iv[2];
64        int     ivlen = 8;
65
66        sc_copy_asn1_entry(c_asn1_des_iv, asn1_des_iv);
67        sc_format_asn1_entry(asn1_des_iv + 0, params, &ivlen, 1);
68        return _sc_asn1_encode(ctx, asn1_des_iv, buf, buflen, depth + 1);
69}
70
71static const struct sc_asn1_entry       c_asn1_pbkdf2_params[] = {
72        { "salt",       SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
73        { "count",      SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
74        { "keyLength",  SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
75        { "prf",        SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE, SC_ASN1_OPTIONAL, NULL, NULL },
76        { NULL, 0, 0, 0, NULL, NULL }
77};
78
79static int
80asn1_decode_pbkdf2_params(sc_context_t *ctx, void **paramp,
81                                const u8 *buf, size_t buflen, int depth)
82{
83        struct sc_pbkdf2_params info;
84        struct sc_asn1_entry asn1_pbkdf2_params[5];
85        int r;
86
87        sc_copy_asn1_entry(c_asn1_pbkdf2_params, asn1_pbkdf2_params);
88        sc_format_asn1_entry(asn1_pbkdf2_params + 0,
89                        info.salt, &info.salt_len, 0);
90        sc_format_asn1_entry(asn1_pbkdf2_params + 1,
91                        &info.iterations, NULL, 0);
92        sc_format_asn1_entry(asn1_pbkdf2_params + 2,
93                        &info.key_length, NULL, 0);
94        sc_format_asn1_entry(asn1_pbkdf2_params + 3,
95                        &info.hash_alg, NULL, 0);
96
97        memset(&info, 0, sizeof(info));
98        info.salt_len = sizeof(info.salt);
99        info.hash_alg.algorithm = SC_ALGORITHM_SHA1;
100
101        r = _sc_asn1_decode(ctx, asn1_pbkdf2_params, buf, buflen, NULL, NULL, 0, depth + 1);
102        if (r < 0)
103                return r;
104
105        *paramp = malloc(sizeof(info));
106        if (!*paramp)
107                return SC_ERROR_OUT_OF_MEMORY;
108        memcpy(*paramp, &info, sizeof(info));
109        return 0;
110}
111
112static int
113asn1_encode_pbkdf2_params(sc_context_t *ctx, void *params,
114                                u8 **buf, size_t *buflen, int depth)
115{
116        struct sc_pbkdf2_params *info;
117        struct sc_asn1_entry asn1_pbkdf2_params[5];
118
119        info = (struct sc_pbkdf2_params *) params;
120
121        sc_copy_asn1_entry(c_asn1_pbkdf2_params, asn1_pbkdf2_params);
122        sc_format_asn1_entry(asn1_pbkdf2_params + 0,
123                        info->salt, &info->salt_len, 1);
124        sc_format_asn1_entry(asn1_pbkdf2_params + 1,
125                        &info->iterations, NULL, 1);
126        if (info->key_length > 0)
127                sc_format_asn1_entry(asn1_pbkdf2_params + 2,
128                                &info->key_length, NULL, 1);
129        if (info->hash_alg.algorithm != SC_ALGORITHM_SHA1)
130                sc_format_asn1_entry(asn1_pbkdf2_params + 3,
131                                &info->hash_alg, NULL, 0);
132
133        return _sc_asn1_encode(ctx, asn1_pbkdf2_params, buf, buflen, depth + 1);
134}
135
136static const struct sc_asn1_entry       c_asn1_pbes2_params[] = {
137        { "keyDerivationAlg", SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
138        { "keyEcnryptionAlg", SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL },
139        { NULL, 0, 0, 0, NULL, NULL }
140};
141
142static int
143asn1_decode_pbes2_params(sc_context_t *ctx, void **paramp,
144                                const u8 *buf, size_t buflen, int depth)
145{
146        struct sc_asn1_entry asn1_pbes2_params[3];
147        struct sc_pbes2_params info;
148        int r;
149
150        sc_copy_asn1_entry(c_asn1_pbes2_params, asn1_pbes2_params);
151        sc_format_asn1_entry(asn1_pbes2_params + 0,
152                                &info.derivation_alg, NULL, 0);
153        sc_format_asn1_entry(asn1_pbes2_params + 1,
154                                &info.key_encr_alg, NULL, 0);
155        memset(&info, 0, sizeof(info));
156
157        r = _sc_asn1_decode(ctx, asn1_pbes2_params, buf, buflen, NULL, NULL, 0, depth + 1);
158        if (r < 0)
159                return r;
160        *paramp = malloc(sizeof(info));
161        if (!*paramp)
162                return SC_ERROR_OUT_OF_MEMORY;
163        memcpy(*paramp, &info, sizeof(info));
164        return 0;
165}
166
167static int
168asn1_encode_pbes2_params(sc_context_t *ctx, void *params,
169                                u8 **buf, size_t *buflen, int depth)
170{
171        struct sc_asn1_entry asn1_pbes2_params[3];
172        struct sc_pbes2_params *info;
173
174        info = (struct sc_pbes2_params *) params;
175        sc_copy_asn1_entry(c_asn1_pbes2_params, asn1_pbes2_params);
176        sc_format_asn1_entry(asn1_pbes2_params + 0,
177                                &info->derivation_alg, NULL, 0);
178        sc_format_asn1_entry(asn1_pbes2_params + 1,
179                                &info->key_encr_alg, NULL, 0);
180        return _sc_asn1_encode(ctx, asn1_pbes2_params, buf, buflen, depth + 1);
181}
182
183static void
184asn1_free_pbes2_params(void *ptr)
185{
186        struct sc_pbes2_params *params = (struct sc_pbes2_params *) ptr;
187
188        sc_asn1_clear_algorithm_id(&params->derivation_alg);
189        sc_asn1_clear_algorithm_id(&params->key_encr_alg);
190        free(params);
191}
192
193static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
194#ifdef SC_ALGORITHM_SHA1
195        /* hmacWithSHA1 */
196        { SC_ALGORITHM_SHA1, {{ 1, 2, 840, 113549, 2, 7 }}, NULL, NULL, NULL },
197        { SC_ALGORITHM_SHA1, {{ 1, 3, 6, 1, 5, 5, 8, 1, 2 }}, NULL, NULL, NULL },
198        /* SHA1 */
199        { SC_ALGORITHM_SHA1, {{ 1, 3, 14, 3, 2, 26, }}, NULL, NULL, NULL },
200#endif
201#ifdef SC_ALGORITHM_MD5
202        { SC_ALGORITHM_MD5, {{ 1, 2, 840, 113549, 2, 5, }}, NULL, NULL, NULL },
203#endif
204#ifdef SC_ALGORITHM_DSA
205        { SC_ALGORITHM_DSA, {{ 1, 2, 840, 10040, 4, 3 }}, NULL, NULL, NULL },
206#endif
207#ifdef SC_ALGORITHM_RSA /* really rsaEncryption */
208        { SC_ALGORITHM_RSA, {{ 1, 2, 840, 113549, 1, 1, 1 }}, NULL, NULL, NULL },
209#endif
210#ifdef SC_ALGORITHM_DH
211        { SC_ALGORITHM_DH, {{ 1, 2, 840, 10046, 2, 1 }}, NULL, NULL, NULL },
212#endif
213#ifdef SC_ALGORITHM_RC2_WRAP /* from CMS */
214        { SC_ALGORITHM_RC2_WRAP,  {{ 1, 2, 840, 113549, 1, 9, 16, 3, 7 }}, NULL, NULL, NULL },
215#endif
216#ifdef SC_ALGORITHM_RC2 /* CBC mode */
217        { SC_ALGORITHM_RC2, {{ 1, 2, 840, 113549, 3, 2 }},
218                        asn1_decode_rc2_params,
219                        asn1_encode_rc2_params },
220#endif
221#ifdef SC_ALGORITHM_DES /* CBC mode */
222        { SC_ALGORITHM_DES, {{ 1, 3, 14, 3, 2, 7 }},
223                        asn1_decode_des_params,
224                        asn1_encode_des_params,
225                        free },
226#endif
227#ifdef SC_ALGORITHM_3DES_WRAP /* from CMS */
228        { SC_ALGORITHM_3DES_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 6 }}, NULL, NULL, NULL },
229#endif
230#ifdef SC_ALGORITHM_3DES /* EDE CBC mode */
231        { SC_ALGORITHM_3DES, {{ 1, 2, 840, 113549, 3, 7 }},
232                        asn1_decode_des_params,
233                        asn1_encode_des_params,
234                        free },
235#endif
236#ifdef SC_ALGORITHM_GOST /* EDE CBC mode */
237        { SC_ALGORITHM_GOST, {{ 1, 2, 4434, 66565, 3, 7 }},
238                        NULL,
239                        NULL,
240                        NULL },
241#endif
242/* We do not support PBES1 because the encryption is weak */
243#ifdef SC_ALGORITHM_PBKDF2
244        { SC_ALGORITHM_PBKDF2, {{ 1, 2, 840, 113549, 1, 5, 12 }},
245                        asn1_decode_pbkdf2_params,
246                        asn1_encode_pbkdf2_params,
247                        free },
248#endif
249#ifdef SC_ALGORITHM_PBES2
250        { SC_ALGORITHM_PBES2, {{ 1, 2, 840, 113549, 1, 5, 13 }},
251                        asn1_decode_pbes2_params,
252                        asn1_encode_pbes2_params,
253                        asn1_free_pbes2_params },
254        { -1, {{ -1 }}, NULL, NULL, NULL }
255#endif
256};
257
258static struct sc_asn1_pkcs15_algorithm_info *
259sc_asn1_get_algorithm_info(const struct sc_algorithm_id *id)
260{
261        struct sc_asn1_pkcs15_algorithm_info *aip;
262
263        aip = algorithm_table;
264        if ((int) id->algorithm < 0) {
265                while (aip->id >= 0) {
266                        const int       *oid1, *oid2;
267                        int             m;
268                       
269                        oid1 = aip->oid.value;
270                        oid2 = id->obj_id.value;
271                        for (m = 0; m < SC_MAX_OBJECT_ID_OCTETS; m++) {
272                                if (oid1[m] == oid2[m])
273                                        continue;
274                                if (oid1[m] > 0 || oid2[m] > 0)
275                                        break;
276                                /* We have a match */
277                                return aip;
278                        }
279                        aip++;
280                }
281        } else {
282                while (aip->id >= 0) {
283                        if (aip->id == (int)id->algorithm)
284                                return aip;
285                        aip++;
286                }
287        }
288        return NULL;
289}
290
291static const struct sc_asn1_entry c_asn1_alg_id[6] = {
292        { "algorithm",  SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL },
293        { "nullParam",  SC_ASN1_NULL, SC_ASN1_TAG_NULL, SC_ASN1_OPTIONAL, NULL, NULL },
294        { NULL, 0, 0, 0, NULL, NULL }
295};
296
297int
298sc_asn1_decode_algorithm_id(sc_context_t *ctx, const u8 *in,
299                            size_t len, struct sc_algorithm_id *id,
300                            int depth)
301{
302        struct sc_asn1_pkcs15_algorithm_info *alg_info;
303        struct sc_asn1_entry asn1_alg_id[3];
304        int r;
305
306        sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
307        sc_format_asn1_entry(asn1_alg_id + 0, &id->obj_id, NULL, 0);
308
309        memset(id, 0, sizeof(*id));
310        r = _sc_asn1_decode(ctx, asn1_alg_id, in, len, &in, &len, 0, depth + 1);
311        if (r < 0)
312                return r;
313
314        /* See if we understand the algorithm, and if we do, check
315         * whether we know how to decode any additional parameters */
316        id->algorithm = (unsigned int ) -1;
317        if ((alg_info = sc_asn1_get_algorithm_info(id)) != NULL) {
318                id->algorithm = alg_info->id;
319                if (alg_info->decode) {
320                        if (asn1_alg_id[1].flags & SC_ASN1_PRESENT)
321                                return SC_ERROR_INVALID_ASN1_OBJECT;
322                        r = alg_info->decode(ctx, &id->params, in, len, depth);
323                }
324        }
325
326        return r;
327}
328
329int
330sc_asn1_encode_algorithm_id(sc_context_t *ctx,
331                            u8 **buf, size_t *len,
332                            const struct sc_algorithm_id *id,
333                            int depth)
334{
335        struct sc_asn1_pkcs15_algorithm_info *alg_info;
336        struct sc_algorithm_id temp_id;
337        struct sc_asn1_entry asn1_alg_id[3];
338        u8 *obj = NULL;
339        size_t obj_len = 0;
340        int r;
341        u8 *tmp;
342
343        alg_info = sc_asn1_get_algorithm_info(id);
344        if (alg_info == NULL) {
345                sc_error(ctx, "Cannot encode unknown algorithm %u.\n",
346                                id->algorithm);
347                return SC_ERROR_INVALID_ARGUMENTS;
348        }
349
350        /* Set the oid if not yet given */
351        if (id->obj_id.value[0] <= 0) {
352                temp_id = *id;
353                temp_id.obj_id = alg_info->oid;
354                id = &temp_id;
355        }
356
357        sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id);
358        sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->obj_id, NULL, 1);
359
360        /* no parameters, write NULL tag */
361        if (!id->params || !alg_info->encode)
362                asn1_alg_id[1].flags |= SC_ASN1_PRESENT;
363
364        r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1);
365        if (r < 0)
366                return r;
367
368        /* Encode any parameters */
369        if (id->params && alg_info->encode) {
370                r = alg_info->encode(ctx, id->params, &obj, &obj_len, depth+1);
371                if (r < 0) {
372                        if (obj)
373                                free(obj);
374                        return r;
375                }
376        }
377
378        if (obj_len) {
379                tmp = (u8 *) realloc(*buf, *len + obj_len);
380                if (!tmp) {
381                        free(*buf);
382                        *buf = NULL;
383                        free(obj);
384                        return SC_ERROR_OUT_OF_MEMORY;
385                }
386                *buf = tmp;
387                memcpy(*buf + *len, obj, obj_len);
388                *len += obj_len;
389                free(obj);
390        }
391
392        return 0;
393}
394
395void
396sc_asn1_clear_algorithm_id(struct sc_algorithm_id *id)
397{
398        struct sc_asn1_pkcs15_algorithm_info *aip;
399
400        if ((aip = sc_asn1_get_algorithm_info(id)) && aip->free)
401                aip->free(id);
402}
Note: See TracBrowser for help on using the browser.