Fix X509_PUBKEY cached key handling.
[openssl.git] / crypto / x509 / x_pubkey.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <stdio.h>
59 #include "internal/cryptlib.h"
60 #include <openssl/asn1t.h>
61 #include <openssl/x509.h>
62 #include "internal/asn1_int.h"
63 #include "internal/evp_int.h"
64 #include "internal/x509_int.h"
65 #include <openssl/rsa.h>
66 #include <openssl/dsa.h>
67
68 struct X509_pubkey_st {
69     X509_ALGOR *algor;
70     ASN1_BIT_STRING *public_key;
71     EVP_PKEY *pkey;
72 };
73
74 static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key);
75
76 /* Minor tweak to operation: free up EVP_PKEY */
77 static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
78                      void *exarg)
79 {
80     if (operation == ASN1_OP_FREE_POST) {
81         X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
82         EVP_PKEY_free(pubkey->pkey);
83     } else if (operation == ASN1_OP_D2I_POST) {
84         /* Attempt to decode public key and cache in pubkey structure. */
85         X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
86         EVP_PKEY_free(pubkey->pkey);
87         /*
88          * Opportunistically decode the key but remove any non fatal errors
89          * from the queue. Subsequent explicit attempts to decode/use the key
90          * will return an appropriate error.
91          */
92         ERR_set_mark();
93         if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1)
94             return 0;
95         ERR_pop_to_mark();
96     }
97     return 1;
98 }
99
100 ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
101         ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
102         ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
103 } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
104
105 IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
106
107 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
108 {
109     X509_PUBKEY *pk = NULL;
110
111     if (x == NULL)
112         return (0);
113
114     if ((pk = X509_PUBKEY_new()) == NULL)
115         goto error;
116
117     if (pkey->ameth) {
118         if (pkey->ameth->pub_encode) {
119             if (!pkey->ameth->pub_encode(pk, pkey)) {
120                 X509err(X509_F_X509_PUBKEY_SET,
121                         X509_R_PUBLIC_KEY_ENCODE_ERROR);
122                 goto error;
123             }
124         } else {
125             X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
126             goto error;
127         }
128     } else {
129         X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
130         goto error;
131     }
132
133     X509_PUBKEY_free(*x);
134     *x = pk;
135     pk->pkey = pkey;
136     EVP_PKEY_up_ref(pkey);
137     return 1;
138
139  error:
140     X509_PUBKEY_free(pk);
141     return 0;
142 }
143
144 /*
145  * Attempt to decode a public key.
146  * Returns 1 on success, 0 for a decode failure and -1 for a fatal
147  * error e.g. malloc failure.
148  */
149
150
151 static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key)
152     {
153     EVP_PKEY *pkey = EVP_PKEY_new();
154
155     if (pkey == NULL) {
156         X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE);
157         return -1;
158     }
159
160     if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) {
161         X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM);
162         goto error;
163     }
164
165     if (pkey->ameth->pub_decode) {
166         /*
167          * Treat any failure of pub_decode as a decode error. In
168          * future we could have different return codes for decode
169          * errors and fatal errors such as malloc failure.
170          */
171         if (!pkey->ameth->pub_decode(pkey, key)) {
172             X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR);
173             goto error;
174         }
175     } else {
176         X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED);
177         goto error;
178     }
179
180     *ppkey = pkey;
181     return 1;
182
183  error:
184     EVP_PKEY_free(pkey);
185     return 0;
186 }
187
188 EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key)
189 {
190     EVP_PKEY *ret = NULL;
191
192     if (key == NULL || key->public_key == NULL)
193         return NULL;
194
195     if (key->pkey != NULL)
196         return key->pkey;
197
198     /*
199      * When the key ASN.1 is initially parsed an attempt is made to
200      * decode the public key and cache the EVP_PKEY structure. If this
201      * operation fails the cached value will be NULL. Parsing continues
202      * to allow parsing of unknown key types or unsupported forms.
203      * We repeat the decode operation so the appropriate errors are left
204      * in the queue.
205      */
206     x509_pubkey_decode(&ret, key);
207     /* If decode doesn't fail something bad happened */
208     if (ret != NULL) {
209         X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR);
210         EVP_PKEY_free(ret);
211     }
212
213     return NULL;
214 }
215
216 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
217 {
218     EVP_PKEY *ret = X509_PUBKEY_get0(key);
219     if (ret != NULL)
220         EVP_PKEY_up_ref(ret);
221     return ret;
222 }
223
224 /*
225  * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
226  * decode as X509_PUBKEY
227  */
228
229 EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
230 {
231     X509_PUBKEY *xpk;
232     EVP_PKEY *pktmp;
233     const unsigned char *q;
234     q = *pp;
235     xpk = d2i_X509_PUBKEY(NULL, &q, length);
236     if (!xpk)
237         return NULL;
238     pktmp = X509_PUBKEY_get(xpk);
239     X509_PUBKEY_free(xpk);
240     if (!pktmp)
241         return NULL;
242     *pp = q;
243     if (a) {
244         EVP_PKEY_free(*a);
245         *a = pktmp;
246     }
247     return pktmp;
248 }
249
250 int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
251 {
252     X509_PUBKEY *xpk = NULL;
253     int ret;
254     if (!a)
255         return 0;
256     if (!X509_PUBKEY_set(&xpk, a))
257         return 0;
258     ret = i2d_X509_PUBKEY(xpk, pp);
259     X509_PUBKEY_free(xpk);
260     return ret;
261 }
262
263 /*
264  * The following are equivalents but which return RSA and DSA keys
265  */
266 #ifndef OPENSSL_NO_RSA
267 RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
268 {
269     EVP_PKEY *pkey;
270     RSA *key;
271     const unsigned char *q;
272     q = *pp;
273     pkey = d2i_PUBKEY(NULL, &q, length);
274     if (!pkey)
275         return NULL;
276     key = EVP_PKEY_get1_RSA(pkey);
277     EVP_PKEY_free(pkey);
278     if (!key)
279         return NULL;
280     *pp = q;
281     if (a) {
282         RSA_free(*a);
283         *a = key;
284     }
285     return key;
286 }
287
288 int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
289 {
290     EVP_PKEY *pktmp;
291     int ret;
292     if (!a)
293         return 0;
294     pktmp = EVP_PKEY_new();
295     if (pktmp == NULL) {
296         ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
297         return 0;
298     }
299     EVP_PKEY_set1_RSA(pktmp, a);
300     ret = i2d_PUBKEY(pktmp, pp);
301     EVP_PKEY_free(pktmp);
302     return ret;
303 }
304 #endif
305
306 #ifndef OPENSSL_NO_DSA
307 DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
308 {
309     EVP_PKEY *pkey;
310     DSA *key;
311     const unsigned char *q;
312     q = *pp;
313     pkey = d2i_PUBKEY(NULL, &q, length);
314     if (!pkey)
315         return NULL;
316     key = EVP_PKEY_get1_DSA(pkey);
317     EVP_PKEY_free(pkey);
318     if (!key)
319         return NULL;
320     *pp = q;
321     if (a) {
322         DSA_free(*a);
323         *a = key;
324     }
325     return key;
326 }
327
328 int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
329 {
330     EVP_PKEY *pktmp;
331     int ret;
332     if (!a)
333         return 0;
334     pktmp = EVP_PKEY_new();
335     if (pktmp == NULL) {
336         ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
337         return 0;
338     }
339     EVP_PKEY_set1_DSA(pktmp, a);
340     ret = i2d_PUBKEY(pktmp, pp);
341     EVP_PKEY_free(pktmp);
342     return ret;
343 }
344 #endif
345
346 #ifndef OPENSSL_NO_EC
347 EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
348 {
349     EVP_PKEY *pkey;
350     EC_KEY *key;
351     const unsigned char *q;
352     q = *pp;
353     pkey = d2i_PUBKEY(NULL, &q, length);
354     if (!pkey)
355         return (NULL);
356     key = EVP_PKEY_get1_EC_KEY(pkey);
357     EVP_PKEY_free(pkey);
358     if (!key)
359         return (NULL);
360     *pp = q;
361     if (a) {
362         EC_KEY_free(*a);
363         *a = key;
364     }
365     return (key);
366 }
367
368 int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
369 {
370     EVP_PKEY *pktmp;
371     int ret;
372     if (!a)
373         return (0);
374     if ((pktmp = EVP_PKEY_new()) == NULL) {
375         ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
376         return (0);
377     }
378     EVP_PKEY_set1_EC_KEY(pktmp, a);
379     ret = i2d_PUBKEY(pktmp, pp);
380     EVP_PKEY_free(pktmp);
381     return (ret);
382 }
383 #endif
384
385 int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
386                            int ptype, void *pval,
387                            unsigned char *penc, int penclen)
388 {
389     if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
390         return 0;
391     if (penc) {
392         OPENSSL_free(pub->public_key->data);
393         pub->public_key->data = penc;
394         pub->public_key->length = penclen;
395         /* Set number of unused bits to zero */
396         pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
397         pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
398     }
399     return 1;
400 }
401
402 int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
403                            const unsigned char **pk, int *ppklen,
404                            X509_ALGOR **pa, X509_PUBKEY *pub)
405 {
406     if (ppkalg)
407         *ppkalg = pub->algor->algorithm;
408     if (pk) {
409         *pk = pub->public_key->data;
410         *ppklen = pub->public_key->length;
411     }
412     if (pa)
413         *pa = pub->algor;
414     return 1;
415 }
416
417 ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
418 {
419     if (x == NULL)
420         return NULL;
421     return x->cert_info.key->public_key;
422 }