~ubuntu-branches/ubuntu/lucid/openssl/lucid-proposed

« back to all changes in this revision

Viewing changes to crypto/asn1/ameth_lib.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-06-13 18:15:46 UTC
  • mto: (11.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090613181546-vbfntai3b009dl1u
Tags: upstream-0.9.8k
ImportĀ upstreamĀ versionĀ 0.9.8k

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
 
2
 * project 2006.
 
3
 */
 
4
/* ====================================================================
 
5
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions
 
9
 * are met:
 
10
 *
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer. 
 
13
 *
 
14
 * 2. Redistributions in binary form must reproduce the above copyright
 
15
 *    notice, this list of conditions and the following disclaimer in
 
16
 *    the documentation and/or other materials provided with the
 
17
 *    distribution.
 
18
 *
 
19
 * 3. All advertising materials mentioning features or use of this
 
20
 *    software must display the following acknowledgment:
 
21
 *    "This product includes software developed by the OpenSSL Project
 
22
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 
23
 *
 
24
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 
25
 *    endorse or promote products derived from this software without
 
26
 *    prior written permission. For written permission, please contact
 
27
 *    licensing@OpenSSL.org.
 
28
 *
 
29
 * 5. Products derived from this software may not be called "OpenSSL"
 
30
 *    nor may "OpenSSL" appear in their names without prior written
 
31
 *    permission of the OpenSSL Project.
 
32
 *
 
33
 * 6. Redistributions of any form whatsoever must retain the following
 
34
 *    acknowledgment:
 
35
 *    "This product includes software developed by the OpenSSL Project
 
36
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 
37
 *
 
38
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 
39
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
40
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
41
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 
42
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
43
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
44
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
45
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
46
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
47
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
48
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
49
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
50
 * ====================================================================
 
51
 *
 
52
 * This product includes cryptographic software written by Eric Young
 
53
 * (eay@cryptsoft.com).  This product includes software written by Tim
 
54
 * Hudson (tjh@cryptsoft.com).
 
55
 *
 
56
 */
 
57
 
 
58
#include <stdio.h>
 
59
#include "cryptlib.h"
 
60
#include <openssl/asn1t.h>
 
61
#include <openssl/x509.h>
 
62
#ifndef OPENSSL_NO_ENGINE
 
63
#include <openssl/engine.h>
 
64
#endif
 
65
#include "asn1_locl.h"
 
66
 
 
67
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
 
68
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
 
69
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
 
70
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
 
71
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
 
72
 
 
73
/* Keep this sorted in type order !! */
 
74
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = 
 
75
        {
 
76
#ifndef OPENSSL_NO_RSA
 
77
        &rsa_asn1_meths[0],
 
78
        &rsa_asn1_meths[1],
 
79
#endif
 
80
#ifndef OPENSSL_NO_DH
 
81
        &dh_asn1_meth,
 
82
#endif
 
83
#ifndef OPENSSL_NO_DSA
 
84
        &dsa_asn1_meths[0],
 
85
        &dsa_asn1_meths[1],
 
86
        &dsa_asn1_meths[2],
 
87
        &dsa_asn1_meths[3],
 
88
        &dsa_asn1_meths[4],
 
89
#endif
 
90
#ifndef OPENSSL_NO_EC
 
91
        &eckey_asn1_meth,
 
92
#endif
 
93
        &hmac_asn1_meth
 
94
        };
 
95
 
 
96
typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
 
97
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
 
98
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
 
99
 
 
100
 
 
101
 
 
102
#ifdef TEST
 
103
void main()
 
104
        {
 
105
        int i;
 
106
        for (i = 0;
 
107
                i < sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 
108
                i++)
 
109
                fprintf(stderr, "Number %d id=%d (%s)\n", i,
 
110
                        standard_methods[i]->pkey_id,
 
111
                        OBJ_nid2sn(standard_methods[i]->pkey_id));
 
112
        }
 
113
#endif
 
114
 
 
115
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
 
116
                           const EVP_PKEY_ASN1_METHOD *, ameth);
 
117
 
 
118
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
 
119
                     const EVP_PKEY_ASN1_METHOD * const *b)
 
120
        {
 
121
        return ((*a)->pkey_id - (*b)->pkey_id);
 
122
        }
 
123
 
 
124
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
 
125
                             const EVP_PKEY_ASN1_METHOD *, ameth);
 
126
 
 
127
int EVP_PKEY_asn1_get_count(void)
 
128
        {
 
129
        int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 
130
        if (app_methods)
 
131
                num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
 
132
        return num;
 
133
        }
 
134
 
 
135
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
 
136
        {
 
137
        int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 
138
        if (idx < 0)
 
139
                return NULL; 
 
140
        if (idx < num)
 
141
                return standard_methods[idx];
 
142
        idx -= num;
 
143
        return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
 
144
        }
 
145
 
 
146
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
 
147
        {
 
148
        EVP_PKEY_ASN1_METHOD tmp;
 
149
        const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
 
150
        tmp.pkey_id = type;
 
151
        if (app_methods)
 
152
                {
 
153
                int idx;
 
154
                idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
 
155
                if (idx >= 0)
 
156
                        return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
 
157
                }
 
158
        ret = OBJ_bsearch_ameth(&t, standard_methods,
 
159
                          sizeof(standard_methods)
 
160
                          /sizeof(EVP_PKEY_ASN1_METHOD *));
 
161
        if (!ret || !*ret)
 
162
                return NULL;
 
163
        return *ret;
 
164
        }
 
165
 
 
166
/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
 
167
 * also search through engines and set *pe to a functional reference
 
168
 * to the engine implementing 'type' or NULL if no engine implements 
 
169
 * it.
 
170
 */
 
171
 
 
172
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
 
173
        {
 
174
        const EVP_PKEY_ASN1_METHOD *t;
 
175
        ENGINE *e;
 
176
 
 
177
        for (;;)
 
178
                {
 
179
                t = pkey_asn1_find(type);
 
180
                if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
 
181
                        break;
 
182
                type = t->pkey_base_id;
 
183
                }
 
184
        if (pe)
 
185
                {
 
186
#ifndef OPENSSL_NO_ENGINE
 
187
                /* type will contain the final unaliased type */
 
188
                e = ENGINE_get_pkey_asn1_meth_engine(type);
 
189
                if (e)
 
190
                        {
 
191
                        *pe = e;
 
192
                        return ENGINE_get_pkey_asn1_meth(e, type);
 
193
                        }
 
194
#endif
 
195
                *pe = NULL;
 
196
                }
 
197
        return t;
 
198
        }
 
199
 
 
200
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
 
201
                                        const char *str, int len)
 
202
        {
 
203
        int i;
 
204
        const EVP_PKEY_ASN1_METHOD *ameth;
 
205
        if (len == -1)
 
206
                len = strlen(str);
 
207
        if (pe)
 
208
                {
 
209
#ifndef OPENSSL_NO_ENGINE
 
210
                ENGINE *e;
 
211
                ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
 
212
                if (ameth)
 
213
                        {
 
214
                        /* Convert structural into
 
215
                         * functional reference
 
216
                         */
 
217
                        if (!ENGINE_init(e))
 
218
                                ameth = NULL;
 
219
                        ENGINE_free(e);
 
220
                        *pe = e;
 
221
                        return ameth;
 
222
                        }
 
223
#endif
 
224
                *pe = NULL;
 
225
                }
 
226
        for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
 
227
                {
 
228
                ameth = EVP_PKEY_asn1_get0(i);
 
229
                if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
 
230
                        continue;
 
231
                if (((int)strlen(ameth->pem_str) == len) && 
 
232
                        !strncasecmp(ameth->pem_str, str, len))
 
233
                        return ameth;
 
234
                }
 
235
        return NULL;
 
236
        }
 
237
 
 
238
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
 
239
        {
 
240
        if (app_methods == NULL)
 
241
                {
 
242
                app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
 
243
                if (!app_methods)
 
244
                        return 0;
 
245
                }
 
246
        if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
 
247
                return 0;
 
248
        sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
 
249
        return 1;
 
250
        }
 
251
 
 
252
int EVP_PKEY_asn1_add_alias(int to, int from)
 
253
        {
 
254
        EVP_PKEY_ASN1_METHOD *ameth;
 
255
        ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
 
256
        if (!ameth)
 
257
                return 0;
 
258
        ameth->pkey_base_id = to;
 
259
        return EVP_PKEY_asn1_add0(ameth);
 
260
        }
 
261
 
 
262
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
 
263
                                const char **pinfo, const char **ppem_str,
 
264
                                        const EVP_PKEY_ASN1_METHOD *ameth)
 
265
        {
 
266
        if (!ameth)
 
267
                return 0;
 
268
        if (ppkey_id)
 
269
                *ppkey_id = ameth->pkey_id;
 
270
        if (ppkey_base_id)
 
271
                *ppkey_base_id = ameth->pkey_base_id;
 
272
        if (ppkey_flags)
 
273
                *ppkey_flags = ameth->pkey_flags;
 
274
        if (pinfo)
 
275
                *pinfo = ameth->info;
 
276
        if (ppem_str)
 
277
                *ppem_str = ameth->pem_str;
 
278
        return 1;
 
279
        }
 
280
 
 
281
const EVP_PKEY_ASN1_METHOD* EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
 
282
        {
 
283
        return pkey->ameth;
 
284
        }
 
285
 
 
286
EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags,
 
287
                                        const char *pem_str, const char *info)
 
288
        {
 
289
        EVP_PKEY_ASN1_METHOD *ameth;
 
290
        ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
 
291
        if (!ameth)
 
292
                return NULL;
 
293
 
 
294
        ameth->pkey_id = id;
 
295
        ameth->pkey_base_id = id;
 
296
        ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
 
297
 
 
298
        if (info)
 
299
                {
 
300
                ameth->info = BUF_strdup(info);
 
301
                if (!ameth->info)
 
302
                        goto err;
 
303
                }
 
304
 
 
305
        if (pem_str)
 
306
                {
 
307
                ameth->pem_str = BUF_strdup(pem_str);
 
308
                if (!ameth->pem_str)
 
309
                        goto err;
 
310
                }
 
311
 
 
312
        ameth->pub_decode = 0;
 
313
        ameth->pub_encode = 0;
 
314
        ameth->pub_cmp = 0;
 
315
        ameth->pub_print = 0;
 
316
 
 
317
        ameth->priv_decode = 0;
 
318
        ameth->priv_encode = 0;
 
319
        ameth->priv_print = 0;
 
320
 
 
321
        ameth->old_priv_encode = 0;
 
322
        ameth->old_priv_decode = 0;
 
323
 
 
324
        ameth->pkey_size = 0;
 
325
        ameth->pkey_bits = 0;
 
326
 
 
327
        ameth->param_decode = 0;
 
328
        ameth->param_encode = 0;
 
329
        ameth->param_missing = 0;
 
330
        ameth->param_copy = 0;
 
331
        ameth->param_cmp = 0;
 
332
        ameth->param_print = 0;
 
333
 
 
334
        ameth->pkey_free = 0;
 
335
        ameth->pkey_ctrl = 0;
 
336
 
 
337
        return ameth;
 
338
 
 
339
        err:
 
340
 
 
341
        EVP_PKEY_asn1_free(ameth);
 
342
        return NULL;
 
343
 
 
344
        }
 
345
 
 
346
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, 
 
347
                        const EVP_PKEY_ASN1_METHOD *src)
 
348
        {
 
349
 
 
350
        dst->pub_decode = src->pub_decode;
 
351
        dst->pub_encode = src->pub_encode;
 
352
        dst->pub_cmp = src->pub_cmp;
 
353
        dst->pub_print = src->pub_print;
 
354
 
 
355
        dst->priv_decode = src->priv_decode;
 
356
        dst->priv_encode = src->priv_encode;
 
357
        dst->priv_print = src->priv_print;
 
358
 
 
359
        dst->old_priv_encode = src->old_priv_encode;
 
360
        dst->old_priv_decode = src->old_priv_decode;
 
361
 
 
362
        dst->pkey_size = src->pkey_size;
 
363
        dst->pkey_bits = src->pkey_bits;
 
364
 
 
365
        dst->param_decode = src->param_decode;
 
366
        dst->param_encode = src->param_encode;
 
367
        dst->param_missing = src->param_missing;
 
368
        dst->param_copy = src->param_copy;
 
369
        dst->param_cmp = src->param_cmp;
 
370
        dst->param_print = src->param_print;
 
371
 
 
372
        dst->pkey_free = src->pkey_free;
 
373
        dst->pkey_ctrl = src->pkey_ctrl;
 
374
 
 
375
        }
 
376
 
 
377
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
 
378
        {
 
379
        if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC))
 
380
                {
 
381
                if (ameth->pem_str)
 
382
                        OPENSSL_free(ameth->pem_str);
 
383
                if (ameth->info)
 
384
                        OPENSSL_free(ameth->info);
 
385
                OPENSSL_free(ameth);
 
386
                }
 
387
        }
 
388
 
 
389
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
 
390
                int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
 
391
                int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
 
392
                int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 
393
                int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 
394
                                                        ASN1_PCTX *pctx),
 
395
                int (*pkey_size)(const EVP_PKEY *pk),
 
396
                int (*pkey_bits)(const EVP_PKEY *pk))
 
397
        {
 
398
        ameth->pub_decode = pub_decode;
 
399
        ameth->pub_encode = pub_encode;
 
400
        ameth->pub_cmp = pub_cmp;
 
401
        ameth->pub_print = pub_print;
 
402
        ameth->pkey_size = pkey_size;
 
403
        ameth->pkey_bits = pkey_bits;
 
404
        }
 
405
 
 
406
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
 
407
                int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf),
 
408
                int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
 
409
                int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 
410
                                                        ASN1_PCTX *pctx))
 
411
        {
 
412
        ameth->priv_decode = priv_decode;
 
413
        ameth->priv_encode = priv_encode;
 
414
        ameth->priv_print = priv_print;
 
415
        }
 
416
 
 
417
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
 
418
                int (*param_decode)(EVP_PKEY *pkey,
 
419
                                const unsigned char **pder, int derlen),
 
420
                int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
 
421
                int (*param_missing)(const EVP_PKEY *pk),
 
422
                int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
 
423
                int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 
424
                int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 
425
                                                        ASN1_PCTX *pctx))
 
426
        {
 
427
        ameth->param_decode = param_decode;
 
428
        ameth->param_encode = param_encode;
 
429
        ameth->param_missing = param_missing;
 
430
        ameth->param_copy = param_copy;
 
431
        ameth->param_cmp = param_cmp;
 
432
        ameth->param_print = param_print;
 
433
        }
 
434
 
 
435
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
 
436
                void (*pkey_free)(EVP_PKEY *pkey))
 
437
        {
 
438
        ameth->pkey_free = pkey_free;
 
439
        }
 
440
 
 
441
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
 
442
                int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
 
443
                                                        long arg1, void *arg2))
 
444
        {
 
445
        ameth->pkey_ctrl = pkey_ctrl;
 
446
        }