]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509/x509_vfy.c
Add compilation of x509_trs
[thirdparty/openssl.git] / crypto / x509 / x509_vfy.c
CommitLineData
d02b48c6 1/* crypto/x509/x509_vfy.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <time.h>
61#include <errno.h>
d02b48c6
RE
62
63#include "cryptlib.h"
17f389bb 64#include <openssl/crypto.h>
ec577822
BM
65#include <openssl/lhash.h>
66#include <openssl/buffer.h>
67#include <openssl/evp.h>
68#include <openssl/asn1.h>
69#include <openssl/x509.h>
11262391 70#include <openssl/x509v3.h>
ec577822 71#include <openssl/objects.h>
d02b48c6 72
d02b48c6 73static int null_callback(int ok,X509_STORE_CTX *e);
11262391 74static int check_chain_purpose(X509_STORE_CTX *ctx);
d02b48c6 75static int internal_verify(X509_STORE_CTX *ctx);
e778802f 76const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
b4cadc6e 77
58964a49
RE
78static STACK *x509_store_ctx_method=NULL;
79static int x509_store_ctx_num=0;
80#if 0
81static int x509_store_num=1;
82static STACK *x509_store_method=NULL;
83#endif
d02b48c6 84
6b691a5c 85static int null_callback(int ok, X509_STORE_CTX *e)
d02b48c6
RE
86 {
87 return(ok);
88 }
89
90#if 0
6b691a5c 91static int x509_subject_cmp(X509 **a, X509 **b)
d02b48c6
RE
92 {
93 return(X509_subject_name_cmp(*a,*b));
94 }
95#endif
96
6b691a5c 97int X509_verify_cert(X509_STORE_CTX *ctx)
d02b48c6
RE
98 {
99 X509 *x,*xtmp,*chain_ss=NULL;
100 X509_NAME *xn;
101 X509_OBJECT obj;
102 int depth,i,ok=0;
103 int num;
104 int (*cb)();
f73e07cf 105 STACK_OF(X509) *sktmp=NULL;
d02b48c6
RE
106
107 if (ctx->cert == NULL)
108 {
109 X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
110 return(-1);
111 }
112
113 cb=ctx->ctx->verify_cb;
114 if (cb == NULL) cb=null_callback;
115
116 /* first we make sure the chain we are going to build is
117 * present and that the first entry is in place */
118 if (ctx->chain == NULL)
119 {
7e258a56
BL
120 if ( ((ctx->chain=sk_X509_new_null()) == NULL) ||
121 (!sk_X509_push(ctx->chain,ctx->cert)))
d02b48c6
RE
122 {
123 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
124 goto end;
125 }
126 CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
127 ctx->last_untrusted=1;
128 }
129
f76d8c47 130 /* We use a temporary STACK so we can chop and hack at it */
f73e07cf
BL
131 if (ctx->untrusted != NULL
132 && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
d02b48c6
RE
133 {
134 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
135 goto end;
136 }
137
7e258a56
BL
138 num=sk_X509_num(ctx->chain);
139 x=sk_X509_value(ctx->chain,num-1);
d02b48c6
RE
140 depth=ctx->depth;
141
142
143 for (;;)
144 {
145 /* If we have enough, we break */
d797727b 146 if (depth < num) break; /* FIXME: If this happens, we should take
a9642be6
BM
147 * note of it and, if appropriate, use the
148 * X509_V_ERR_CERT_CHAIN_TOO_LONG error
149 * code later.
150 */
d02b48c6
RE
151
152 /* If we are self signed, we break */
153 xn=X509_get_issuer_name(x);
154 if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0)
155 break;
156
157 /* If we were passed a cert chain, use it first */
158 if (ctx->untrusted != NULL)
159 {
160 xtmp=X509_find_by_subject(sktmp,xn);
161 if (xtmp != NULL)
162 {
7e258a56 163 if (!sk_X509_push(ctx->chain,xtmp))
d02b48c6
RE
164 {
165 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
166 goto end;
167 }
168 CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
f73e07cf 169 sk_X509_delete_ptr(sktmp,xtmp);
d02b48c6
RE
170 ctx->last_untrusted++;
171 x=xtmp;
172 num++;
173 /* reparse the full chain for
174 * the next one */
175 continue;
176 }
177 }
178 break;
179 }
180
181 /* at this point, chain should contain a list of untrusted
182 * certificates. We now need to add at least one trusted one,
183 * if possible, otherwise we complain. */
184
7e258a56
BL
185 i=sk_X509_num(ctx->chain);
186 x=sk_X509_value(ctx->chain,i-1);
f76d8c47
DSH
187 xn = X509_get_subject_name(x);
188 if (X509_NAME_cmp(xn,X509_get_issuer_name(x))
d02b48c6
RE
189 == 0)
190 {
191 /* we have a self signed certificate */
7e258a56 192 if (sk_X509_num(ctx->chain) == 1)
d02b48c6 193 {
f76d8c47
DSH
194 /* We have a single self signed certificate: see if
195 * we can find it in the store. We must have an exact
196 * match to avoid possible impersonation.
197 */
198 ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
199 if ((ok != X509_LU_X509) || X509_cmp(x, obj.data.x509))
200 {
201 ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
202 ctx->current_cert=x;
203 ctx->error_depth=i-1;
204 if(ok == X509_LU_X509) X509_OBJECT_free_contents(&obj);
205 ok=cb(0,ctx);
206 if (!ok) goto end;
207 }
208 else
209 {
210 /* We have a match: replace certificate with store version
211 * so we get any trust settings.
212 */
213 X509_free(x);
214 x = obj.data.x509;
215 sk_X509_set(ctx->chain, i - 1, x);
216 ctx->last_untrusted=0;
217 }
d02b48c6
RE
218 }
219 else
220 {
221 /* worry more about this one elsewhere */
7e258a56 222 chain_ss=sk_X509_pop(ctx->chain);
d02b48c6
RE
223 ctx->last_untrusted--;
224 num--;
7e258a56 225 x=sk_X509_value(ctx->chain,num-1);
d02b48c6
RE
226 }
227 }
228
229 /* We now lookup certs from the certificate store */
230 for (;;)
231 {
232 /* If we have enough, we break */
7f89714e 233 if (depth < num) break;
d02b48c6
RE
234
235 /* If we are self signed, we break */
236 xn=X509_get_issuer_name(x);
237 if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0)
238 break;
239
240 ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
241 if (ok != X509_LU_X509)
242 {
243 if (ok == X509_LU_RETRY)
244 {
245 X509_OBJECT_free_contents(&obj);
246 X509err(X509_F_X509_VERIFY_CERT,X509_R_SHOULD_RETRY);
247 return(ok);
248 }
249 else if (ok != X509_LU_FAIL)
250 {
251 X509_OBJECT_free_contents(&obj);
252 /* not good :-(, break anyway */
253 return(ok);
254 }
255 break;
256 }
257 x=obj.data.x509;
7e258a56 258 if (!sk_X509_push(ctx->chain,obj.data.x509))
d02b48c6
RE
259 {
260 X509_OBJECT_free_contents(&obj);
261 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
262 return(0);
263 }
264 num++;
265 }
266
267 /* we now have our chain, lets check it... */
268 xn=X509_get_issuer_name(x);
269 if (X509_NAME_cmp(X509_get_subject_name(x),xn) != 0)
270 {
271 if ((chain_ss == NULL) || (X509_NAME_cmp(X509_get_subject_name(chain_ss),xn) != 0))
272 {
273 if (ctx->last_untrusted >= num)
274 ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
275 else
276 ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
277 ctx->current_cert=x;
278 }
279 else
280 {
281
7e258a56 282 sk_X509_push(ctx->chain,chain_ss);
d02b48c6
RE
283 num++;
284 ctx->last_untrusted=num;
285 ctx->current_cert=chain_ss;
286 ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
287 chain_ss=NULL;
288 }
289
290 ctx->error_depth=num-1;
291 ok=cb(0,ctx);
292 if (!ok) goto end;
293 }
294
11262391
DSH
295 /* We have the chain complete: now we need to check its purpose */
296 if(ctx->chain_purpose > 0) ok = check_chain_purpose(ctx);
297
298 if(!ok) goto end;
299
d02b48c6
RE
300 /* We may as well copy down any DSA parameters that are required */
301 X509_get_pubkey_parameters(NULL,ctx->chain);
302
303 /* At this point, we have a chain and just need to verify it */
304 if (ctx->ctx->verify != NULL)
305 ok=ctx->ctx->verify(ctx);
306 else
307 ok=internal_verify(ctx);
dfeab068
RE
308 if (0)
309 {
d02b48c6 310end:
dfeab068
RE
311 X509_get_pubkey_parameters(NULL,ctx->chain);
312 }
f73e07cf 313 if (sktmp != NULL) sk_X509_free(sktmp);
d02b48c6
RE
314 if (chain_ss != NULL) X509_free(chain_ss);
315 return(ok);
316 }
317
11262391
DSH
318/* Check a certificate chains extensions for consistency
319 * with the supplied purpose
320 */
321
322static int check_chain_purpose(X509_STORE_CTX *ctx)
323{
324#ifdef NO_CHAIN_VERIFY
325 return 1;
326#else
327 int i, ok=0;
328 X509 *x;
329 int (*cb)();
330 cb=ctx->ctx->verify_cb;
331 if (cb == NULL) cb=null_callback;
332 /* Check all untrusted certificates */
333 for(i = 0; i < ctx->last_untrusted; i++) {
334 x = sk_X509_value(ctx->chain, i);
335 if(!X509_check_purpose(x, ctx->chain_purpose, i)) {
336 if(i) ctx->error = X509_V_ERR_INVALID_CA;
337 else ctx->error = X509_V_ERR_INVALID_PURPOSE;
338 ctx->error_depth = i;
339 ctx->current_cert = x;
340 ok=cb(0,ctx);
341 if(!ok) goto end;
342 }
343 /* Check pathlen */
344 if((i > 1) && (x->ex_pathlen != -1)
345 && (i > (x->ex_pathlen + 1))) {
346 ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
347 ctx->error_depth = i;
348 ctx->current_cert = x;
349 ok=cb(0,ctx);
350 if(!ok) goto end;
351 }
352 }
353 ok = 1;
354 end:
355 return(ok);
356#endif
357}
358
6b691a5c 359static int internal_verify(X509_STORE_CTX *ctx)
d02b48c6
RE
360 {
361 int i,ok=0,n;
362 X509 *xs,*xi;
363 EVP_PKEY *pkey=NULL;
364 int (*cb)();
365
366 cb=ctx->ctx->verify_cb;
367 if (cb == NULL) cb=null_callback;
368
7e258a56 369 n=sk_X509_num(ctx->chain);
d02b48c6
RE
370 ctx->error_depth=n-1;
371 n--;
7e258a56 372 xi=sk_X509_value(ctx->chain,n);
d02b48c6
RE
373 if (X509_NAME_cmp(X509_get_subject_name(xi),
374 X509_get_issuer_name(xi)) == 0)
375 xs=xi;
376 else
377 {
378 if (n <= 0)
379 {
380 ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
381 ctx->current_cert=xi;
382 ok=cb(0,ctx);
383 goto end;
384 }
385 else
386 {
387 n--;
388 ctx->error_depth=n;
7e258a56 389 xs=sk_X509_value(ctx->chain,n);
d02b48c6
RE
390 }
391 }
392
393/* ctx->error=0; not needed */
394 while (n >= 0)
395 {
396 ctx->error_depth=n;
397 if (!xs->valid)
398 {
399 if ((pkey=X509_get_pubkey(xi)) == NULL)
400 {
401 ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
402 ctx->current_cert=xi;
403 ok=(*cb)(0,ctx);
404 if (!ok) goto end;
405 }
406 if (X509_verify(xs,pkey) <= 0)
407 {
cfcf6453 408 EVP_PKEY_free(pkey);
d02b48c6
RE
409 ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
410 ctx->current_cert=xs;
411 ok=(*cb)(0,ctx);
412 if (!ok) goto end;
413 }
cfcf6453 414 EVP_PKEY_free(pkey);
d02b48c6
RE
415 pkey=NULL;
416
417 i=X509_cmp_current_time(X509_get_notBefore(xs));
418 if (i == 0)
419 {
420 ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
421 ctx->current_cert=xs;
422 ok=(*cb)(0,ctx);
423 if (!ok) goto end;
424 }
425 if (i > 0)
426 {
427 ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
428 ctx->current_cert=xs;
429 ok=(*cb)(0,ctx);
430 if (!ok) goto end;
431 }
432 xs->valid=1;
433 }
434
435 i=X509_cmp_current_time(X509_get_notAfter(xs));
436 if (i == 0)
437 {
438 ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
439 ctx->current_cert=xs;
440 ok=(*cb)(0,ctx);
441 if (!ok) goto end;
442 }
443
444 if (i < 0)
445 {
446 ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
447 ctx->current_cert=xs;
448 ok=(*cb)(0,ctx);
449 if (!ok) goto end;
450 }
451
452 /* CRL CHECK */
453
454 /* The last error (if any) is still in the error value */
455 ctx->current_cert=xs;
456 ok=(*cb)(1,ctx);
457 if (!ok) goto end;
458
459 n--;
460 if (n >= 0)
461 {
462 xi=xs;
7e258a56 463 xs=sk_X509_value(ctx->chain,n);
d02b48c6
RE
464 }
465 }
466 ok=1;
467end:
468 return(ok);
469 }
470
6b691a5c 471int X509_cmp_current_time(ASN1_UTCTIME *ctm)
d02b48c6
RE
472 {
473 char *str;
474 ASN1_UTCTIME atm;
475 time_t offset;
476 char buff1[24],buff2[24],*p;
477 int i,j;
478
479 p=buff1;
480 i=ctm->length;
481 str=(char *)ctm->data;
482 if ((i < 11) || (i > 17)) return(0);
483 memcpy(p,str,10);
484 p+=10;
485 str+=10;
486
487 if ((*str == 'Z') || (*str == '-') || (*str == '+'))
488 { *(p++)='0'; *(p++)='0'; }
489 else { *(p++)= *(str++); *(p++)= *(str++); }
490 *(p++)='Z';
491 *(p++)='\0';
492
493 if (*str == 'Z')
494 offset=0;
495 else
496 {
497 if ((*str != '+') && (str[5] != '-'))
498 return(0);
499 offset=((str[1]-'0')*10+(str[2]-'0'))*60;
500 offset+=(str[3]-'0')*10+(str[4]-'0');
501 if (*str == '-')
dfeab068 502 offset= -offset;
d02b48c6
RE
503 }
504 atm.type=V_ASN1_UTCTIME;
505 atm.length=sizeof(buff2);
506 atm.data=(unsigned char *)buff2;
507
58964a49 508 X509_gmtime_adj(&atm,-offset);
d02b48c6
RE
509
510 i=(buff1[0]-'0')*10+(buff1[1]-'0');
adbfb083 511 if (i < 50) i+=100; /* cf. RFC 2459 */
d02b48c6 512 j=(buff2[0]-'0')*10+(buff2[1]-'0');
20232a9c 513 if (j < 50) j+=100;
d02b48c6
RE
514
515 if (i < j) return (-1);
516 if (i > j) return (1);
517 i=strcmp(buff1,buff2);
518 if (i == 0) /* wait a second then return younger :-) */
519 return(-1);
520 else
521 return(i);
522 }
523
6b691a5c 524ASN1_UTCTIME *X509_gmtime_adj(ASN1_UTCTIME *s, long adj)
d02b48c6
RE
525 {
526 time_t t;
527
528 time(&t);
529 t+=adj;
530 return(ASN1_UTCTIME_set(s,t));
531 }
532
7e258a56 533int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
d02b48c6
RE
534 {
535 EVP_PKEY *ktmp=NULL,*ktmp2;
536 int i,j;
537
538 if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return(1);
539
7e258a56 540 for (i=0; i<sk_X509_num(chain); i++)
d02b48c6 541 {
7e258a56 542 ktmp=X509_get_pubkey(sk_X509_value(chain,i));
d02b48c6
RE
543 if (ktmp == NULL)
544 {
545 X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
546 return(0);
547 }
548 if (!EVP_PKEY_missing_parameters(ktmp))
549 break;
550 else
551 {
cfcf6453 552 EVP_PKEY_free(ktmp);
d02b48c6
RE
553 ktmp=NULL;
554 }
555 }
556 if (ktmp == NULL)
557 {
558 X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
559 return(0);
560 }
561
562 /* first, populate the other certs */
563 for (j=i-1; j >= 0; j--)
564 {
7e258a56 565 ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
d02b48c6 566 EVP_PKEY_copy_parameters(ktmp2,ktmp);
cfcf6453 567 EVP_PKEY_free(ktmp2);
d02b48c6
RE
568 }
569
cfcf6453
DSH
570 if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
571 EVP_PKEY_free(ktmp);
d02b48c6
RE
572 return(1);
573 }
574
6b691a5c 575int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
d02b48c6
RE
576 {
577 X509_OBJECT *obj,*r;
578 int ret=1;
579
580 if (x == NULL) return(0);
581 obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT));
582 if (obj == NULL)
583 {
584 X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE);
585 return(0);
586 }
587 obj->type=X509_LU_X509;
588 obj->data.x509=x;
589
590 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
591
592 X509_OBJECT_up_ref_count(obj);
593
594 r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj);
595 if (r != NULL)
596 { /* oops, put it back */
597 lh_delete(ctx->certs,(char *)obj);
598 X509_OBJECT_free_contents(obj);
599 Free(obj);
600 lh_insert(ctx->certs,(char *)r);
601 X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE);
602 ret=0;
603 }
604
605 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
606
607 return(ret);
608 }
609
6b691a5c 610int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
58964a49
RE
611 {
612 X509_OBJECT *obj,*r;
613 int ret=1;
614
615 if (x == NULL) return(0);
616 obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT));
617 if (obj == NULL)
618 {
619 X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE);
620 return(0);
621 }
622 obj->type=X509_LU_CRL;
623 obj->data.crl=x;
624
625 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
626
627 X509_OBJECT_up_ref_count(obj);
628
629 r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj);
630 if (r != NULL)
631 { /* oops, put it back */
632 lh_delete(ctx->certs,(char *)obj);
633 X509_OBJECT_free_contents(obj);
634 Free(obj);
635 lh_insert(ctx->certs,(char *)r);
636 X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE);
637 ret=0;
638 }
639
640 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
641
642 return(ret);
643 }
644
6b691a5c
UM
645int X509_STORE_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(),
646 int (*dup_func)(), void (*free_func)())
58964a49
RE
647 {
648 x509_store_ctx_num++;
649 return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1,
650 &x509_store_ctx_method,
651 argl,argp,new_func,dup_func,free_func));
652 }
653
6b691a5c 654int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
58964a49
RE
655 {
656 return(CRYPTO_set_ex_data(&ctx->ex_data,idx,data));
657 }
658
6b691a5c 659void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
58964a49
RE
660 {
661 return(CRYPTO_get_ex_data(&ctx->ex_data,idx));
662 }
663
6b691a5c 664int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
58964a49
RE
665 {
666 return(ctx->error);
667 }
668
6b691a5c 669void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
58964a49
RE
670 {
671 ctx->error=err;
672 }
673
6b691a5c 674int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
58964a49
RE
675 {
676 return(ctx->error_depth);
677 }
678
6b691a5c 679X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
58964a49
RE
680 {
681 return(ctx->current_cert);
682 }
683
7e258a56 684STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
58964a49
RE
685 {
686 return(ctx->chain);
687 }
688
6b691a5c 689void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
58964a49
RE
690 {
691 ctx->cert=x;
692 }
693
6b691a5c 694void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
58964a49
RE
695 {
696 ctx->untrusted=sk;
697 }
698
11262391
DSH
699void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose)
700 {
701 ctx->chain_purpose = purpose;
702 }
703
704void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose)
705 {
706 ctx->trust_purpose = purpose;
707 }
708
f73e07cf
BL
709IMPLEMENT_STACK_OF(X509)
710IMPLEMENT_ASN1_SET_OF(X509)
d500de16 711
f73e07cf 712IMPLEMENT_STACK_OF(X509_NAME)
d500de16 713
f5fedc04 714IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
d500de16 715IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)