]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509/x509_vfy.c
Add part of chain verify SSL support code: not complete or doing anything
[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);
51630a37 75static int check_trust(X509_STORE_CTX *ctx);
d02b48c6 76static int internal_verify(X509_STORE_CTX *ctx);
e778802f 77const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
b4cadc6e 78
58964a49
RE
79static STACK *x509_store_ctx_method=NULL;
80static int x509_store_ctx_num=0;
81#if 0
82static int x509_store_num=1;
83static STACK *x509_store_method=NULL;
84#endif
d02b48c6 85
6b691a5c 86static int null_callback(int ok, X509_STORE_CTX *e)
d02b48c6
RE
87 {
88 return(ok);
89 }
90
91#if 0
6b691a5c 92static int x509_subject_cmp(X509 **a, X509 **b)
d02b48c6
RE
93 {
94 return(X509_subject_name_cmp(*a,*b));
95 }
96#endif
97
6b691a5c 98int X509_verify_cert(X509_STORE_CTX *ctx)
d02b48c6
RE
99 {
100 X509 *x,*xtmp,*chain_ss=NULL;
101 X509_NAME *xn;
102 X509_OBJECT obj;
103 int depth,i,ok=0;
104 int num;
105 int (*cb)();
f73e07cf 106 STACK_OF(X509) *sktmp=NULL;
d02b48c6
RE
107
108 if (ctx->cert == NULL)
109 {
110 X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
111 return(-1);
112 }
113
114 cb=ctx->ctx->verify_cb;
115 if (cb == NULL) cb=null_callback;
116
117 /* first we make sure the chain we are going to build is
118 * present and that the first entry is in place */
119 if (ctx->chain == NULL)
120 {
7e258a56
BL
121 if ( ((ctx->chain=sk_X509_new_null()) == NULL) ||
122 (!sk_X509_push(ctx->chain,ctx->cert)))
d02b48c6
RE
123 {
124 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
125 goto end;
126 }
127 CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
128 ctx->last_untrusted=1;
129 }
130
f76d8c47 131 /* We use a temporary STACK so we can chop and hack at it */
f73e07cf
BL
132 if (ctx->untrusted != NULL
133 && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
d02b48c6
RE
134 {
135 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
136 goto end;
137 }
138
7e258a56
BL
139 num=sk_X509_num(ctx->chain);
140 x=sk_X509_value(ctx->chain,num-1);
d02b48c6
RE
141 depth=ctx->depth;
142
143
144 for (;;)
145 {
146 /* If we have enough, we break */
d797727b 147 if (depth < num) break; /* FIXME: If this happens, we should take
a9642be6
BM
148 * note of it and, if appropriate, use the
149 * X509_V_ERR_CERT_CHAIN_TOO_LONG error
150 * code later.
151 */
d02b48c6
RE
152
153 /* If we are self signed, we break */
154 xn=X509_get_issuer_name(x);
155 if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0)
156 break;
157
158 /* If we were passed a cert chain, use it first */
159 if (ctx->untrusted != NULL)
160 {
161 xtmp=X509_find_by_subject(sktmp,xn);
162 if (xtmp != NULL)
163 {
7e258a56 164 if (!sk_X509_push(ctx->chain,xtmp))
d02b48c6
RE
165 {
166 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
167 goto end;
168 }
169 CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
f73e07cf 170 sk_X509_delete_ptr(sktmp,xtmp);
d02b48c6
RE
171 ctx->last_untrusted++;
172 x=xtmp;
173 num++;
174 /* reparse the full chain for
175 * the next one */
176 continue;
177 }
178 }
179 break;
180 }
181
182 /* at this point, chain should contain a list of untrusted
183 * certificates. We now need to add at least one trusted one,
184 * if possible, otherwise we complain. */
185
7e258a56
BL
186 i=sk_X509_num(ctx->chain);
187 x=sk_X509_value(ctx->chain,i-1);
f76d8c47
DSH
188 xn = X509_get_subject_name(x);
189 if (X509_NAME_cmp(xn,X509_get_issuer_name(x))
d02b48c6
RE
190 == 0)
191 {
192 /* we have a self signed certificate */
7e258a56 193 if (sk_X509_num(ctx->chain) == 1)
d02b48c6 194 {
f76d8c47
DSH
195 /* We have a single self signed certificate: see if
196 * we can find it in the store. We must have an exact
197 * match to avoid possible impersonation.
198 */
199 ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
200 if ((ok != X509_LU_X509) || X509_cmp(x, obj.data.x509))
201 {
202 ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
203 ctx->current_cert=x;
204 ctx->error_depth=i-1;
205 if(ok == X509_LU_X509) X509_OBJECT_free_contents(&obj);
206 ok=cb(0,ctx);
207 if (!ok) goto end;
208 }
209 else
210 {
211 /* We have a match: replace certificate with store version
212 * so we get any trust settings.
213 */
214 X509_free(x);
215 x = obj.data.x509;
216 sk_X509_set(ctx->chain, i - 1, x);
217 ctx->last_untrusted=0;
218 }
d02b48c6
RE
219 }
220 else
221 {
222 /* worry more about this one elsewhere */
7e258a56 223 chain_ss=sk_X509_pop(ctx->chain);
d02b48c6
RE
224 ctx->last_untrusted--;
225 num--;
7e258a56 226 x=sk_X509_value(ctx->chain,num-1);
d02b48c6
RE
227 }
228 }
229
230 /* We now lookup certs from the certificate store */
231 for (;;)
232 {
233 /* If we have enough, we break */
7f89714e 234 if (depth < num) break;
d02b48c6
RE
235
236 /* If we are self signed, we break */
237 xn=X509_get_issuer_name(x);
238 if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0)
239 break;
240
241 ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
242 if (ok != X509_LU_X509)
243 {
244 if (ok == X509_LU_RETRY)
245 {
246 X509_OBJECT_free_contents(&obj);
247 X509err(X509_F_X509_VERIFY_CERT,X509_R_SHOULD_RETRY);
248 return(ok);
249 }
250 else if (ok != X509_LU_FAIL)
251 {
252 X509_OBJECT_free_contents(&obj);
253 /* not good :-(, break anyway */
254 return(ok);
255 }
256 break;
257 }
258 x=obj.data.x509;
7e258a56 259 if (!sk_X509_push(ctx->chain,obj.data.x509))
d02b48c6
RE
260 {
261 X509_OBJECT_free_contents(&obj);
262 X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
263 return(0);
264 }
265 num++;
266 }
267
268 /* we now have our chain, lets check it... */
269 xn=X509_get_issuer_name(x);
270 if (X509_NAME_cmp(X509_get_subject_name(x),xn) != 0)
271 {
272 if ((chain_ss == NULL) || (X509_NAME_cmp(X509_get_subject_name(chain_ss),xn) != 0))
273 {
274 if (ctx->last_untrusted >= num)
275 ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
276 else
277 ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
278 ctx->current_cert=x;
279 }
280 else
281 {
282
7e258a56 283 sk_X509_push(ctx->chain,chain_ss);
d02b48c6
RE
284 num++;
285 ctx->last_untrusted=num;
286 ctx->current_cert=chain_ss;
287 ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
288 chain_ss=NULL;
289 }
290
291 ctx->error_depth=num-1;
292 ok=cb(0,ctx);
293 if (!ok) goto end;
294 }
295
11262391 296 /* We have the chain complete: now we need to check its purpose */
13938ace 297 if(ctx->purpose > 0) ok = check_chain_purpose(ctx);
11262391
DSH
298
299 if(!ok) goto end;
300
51630a37
DSH
301 /* The chain extensions are OK: check trust */
302
13938ace 303 if(ctx->trust > 0) ok = check_trust(ctx);
51630a37
DSH
304
305 if(!ok) goto end;
306
d02b48c6
RE
307 /* We may as well copy down any DSA parameters that are required */
308 X509_get_pubkey_parameters(NULL,ctx->chain);
309
310 /* At this point, we have a chain and just need to verify it */
311 if (ctx->ctx->verify != NULL)
312 ok=ctx->ctx->verify(ctx);
313 else
314 ok=internal_verify(ctx);
dfeab068
RE
315 if (0)
316 {
d02b48c6 317end:
dfeab068
RE
318 X509_get_pubkey_parameters(NULL,ctx->chain);
319 }
f73e07cf 320 if (sktmp != NULL) sk_X509_free(sktmp);
d02b48c6
RE
321 if (chain_ss != NULL) X509_free(chain_ss);
322 return(ok);
323 }
324
11262391
DSH
325/* Check a certificate chains extensions for consistency
326 * with the supplied purpose
327 */
328
329static int check_chain_purpose(X509_STORE_CTX *ctx)
330{
331#ifdef NO_CHAIN_VERIFY
332 return 1;
333#else
334 int i, ok=0;
335 X509 *x;
336 int (*cb)();
337 cb=ctx->ctx->verify_cb;
338 if (cb == NULL) cb=null_callback;
339 /* Check all untrusted certificates */
340 for(i = 0; i < ctx->last_untrusted; i++) {
341 x = sk_X509_value(ctx->chain, i);
13938ace 342 if(!X509_check_purpose(x, ctx->purpose, i)) {
11262391
DSH
343 if(i) ctx->error = X509_V_ERR_INVALID_CA;
344 else ctx->error = X509_V_ERR_INVALID_PURPOSE;
345 ctx->error_depth = i;
346 ctx->current_cert = x;
347 ok=cb(0,ctx);
348 if(!ok) goto end;
349 }
350 /* Check pathlen */
351 if((i > 1) && (x->ex_pathlen != -1)
352 && (i > (x->ex_pathlen + 1))) {
353 ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
354 ctx->error_depth = i;
355 ctx->current_cert = x;
356 ok=cb(0,ctx);
357 if(!ok) goto end;
358 }
359 }
360 ok = 1;
361 end:
362 return(ok);
363#endif
364}
365
51630a37
DSH
366static int check_trust(X509_STORE_CTX *ctx)
367{
368#ifdef NO_CHAIN_VERIFY
369 return 1;
370#else
371 int i, ok;
372 X509 *x;
373 int (*cb)();
374 cb=ctx->ctx->verify_cb;
375 if (cb == NULL) cb=null_callback;
376/* For now just check the last certificate in the chain */
377 i = sk_X509_num(ctx->chain) - 1;
378 x = sk_X509_value(ctx->chain, i);
13938ace 379 ok = X509_check_trust(x, ctx->trust, 0);
51630a37
DSH
380 if(ok == X509_TRUST_TRUSTED) return 1;
381 ctx->error_depth = sk_X509_num(ctx->chain) - 1;
382 ctx->current_cert = x;
383 if(ok == X509_TRUST_REJECTED) ctx->error = X509_V_ERR_CERT_REJECTED;
384 else ctx->error = X509_V_ERR_CERT_UNTRUSTED;
385 ok = cb(0, ctx);
386 return(ok);
387#endif
388}
389
6b691a5c 390static int internal_verify(X509_STORE_CTX *ctx)
d02b48c6
RE
391 {
392 int i,ok=0,n;
393 X509 *xs,*xi;
394 EVP_PKEY *pkey=NULL;
395 int (*cb)();
396
397 cb=ctx->ctx->verify_cb;
398 if (cb == NULL) cb=null_callback;
399
7e258a56 400 n=sk_X509_num(ctx->chain);
d02b48c6
RE
401 ctx->error_depth=n-1;
402 n--;
7e258a56 403 xi=sk_X509_value(ctx->chain,n);
d02b48c6
RE
404 if (X509_NAME_cmp(X509_get_subject_name(xi),
405 X509_get_issuer_name(xi)) == 0)
406 xs=xi;
407 else
408 {
409 if (n <= 0)
410 {
411 ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
412 ctx->current_cert=xi;
413 ok=cb(0,ctx);
414 goto end;
415 }
416 else
417 {
418 n--;
419 ctx->error_depth=n;
7e258a56 420 xs=sk_X509_value(ctx->chain,n);
d02b48c6
RE
421 }
422 }
423
424/* ctx->error=0; not needed */
425 while (n >= 0)
426 {
427 ctx->error_depth=n;
428 if (!xs->valid)
429 {
430 if ((pkey=X509_get_pubkey(xi)) == NULL)
431 {
432 ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
433 ctx->current_cert=xi;
434 ok=(*cb)(0,ctx);
435 if (!ok) goto end;
436 }
437 if (X509_verify(xs,pkey) <= 0)
438 {
cfcf6453 439 EVP_PKEY_free(pkey);
d02b48c6
RE
440 ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
441 ctx->current_cert=xs;
442 ok=(*cb)(0,ctx);
443 if (!ok) goto end;
444 }
cfcf6453 445 EVP_PKEY_free(pkey);
d02b48c6
RE
446 pkey=NULL;
447
448 i=X509_cmp_current_time(X509_get_notBefore(xs));
449 if (i == 0)
450 {
451 ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
452 ctx->current_cert=xs;
453 ok=(*cb)(0,ctx);
454 if (!ok) goto end;
455 }
456 if (i > 0)
457 {
458 ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
459 ctx->current_cert=xs;
460 ok=(*cb)(0,ctx);
461 if (!ok) goto end;
462 }
463 xs->valid=1;
464 }
465
466 i=X509_cmp_current_time(X509_get_notAfter(xs));
467 if (i == 0)
468 {
469 ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
470 ctx->current_cert=xs;
471 ok=(*cb)(0,ctx);
472 if (!ok) goto end;
473 }
474
475 if (i < 0)
476 {
477 ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
478 ctx->current_cert=xs;
479 ok=(*cb)(0,ctx);
480 if (!ok) goto end;
481 }
482
483 /* CRL CHECK */
484
485 /* The last error (if any) is still in the error value */
486 ctx->current_cert=xs;
487 ok=(*cb)(1,ctx);
488 if (!ok) goto end;
489
490 n--;
491 if (n >= 0)
492 {
493 xi=xs;
7e258a56 494 xs=sk_X509_value(ctx->chain,n);
d02b48c6
RE
495 }
496 }
497 ok=1;
498end:
499 return(ok);
500 }
501
6b691a5c 502int X509_cmp_current_time(ASN1_UTCTIME *ctm)
d02b48c6
RE
503 {
504 char *str;
505 ASN1_UTCTIME atm;
506 time_t offset;
507 char buff1[24],buff2[24],*p;
508 int i,j;
509
510 p=buff1;
511 i=ctm->length;
512 str=(char *)ctm->data;
513 if ((i < 11) || (i > 17)) return(0);
514 memcpy(p,str,10);
515 p+=10;
516 str+=10;
517
518 if ((*str == 'Z') || (*str == '-') || (*str == '+'))
519 { *(p++)='0'; *(p++)='0'; }
520 else { *(p++)= *(str++); *(p++)= *(str++); }
521 *(p++)='Z';
522 *(p++)='\0';
523
524 if (*str == 'Z')
525 offset=0;
526 else
527 {
528 if ((*str != '+') && (str[5] != '-'))
529 return(0);
530 offset=((str[1]-'0')*10+(str[2]-'0'))*60;
531 offset+=(str[3]-'0')*10+(str[4]-'0');
532 if (*str == '-')
dfeab068 533 offset= -offset;
d02b48c6
RE
534 }
535 atm.type=V_ASN1_UTCTIME;
536 atm.length=sizeof(buff2);
537 atm.data=(unsigned char *)buff2;
538
58964a49 539 X509_gmtime_adj(&atm,-offset);
d02b48c6
RE
540
541 i=(buff1[0]-'0')*10+(buff1[1]-'0');
adbfb083 542 if (i < 50) i+=100; /* cf. RFC 2459 */
d02b48c6 543 j=(buff2[0]-'0')*10+(buff2[1]-'0');
20232a9c 544 if (j < 50) j+=100;
d02b48c6
RE
545
546 if (i < j) return (-1);
547 if (i > j) return (1);
548 i=strcmp(buff1,buff2);
549 if (i == 0) /* wait a second then return younger :-) */
550 return(-1);
551 else
552 return(i);
553 }
554
6b691a5c 555ASN1_UTCTIME *X509_gmtime_adj(ASN1_UTCTIME *s, long adj)
d02b48c6
RE
556 {
557 time_t t;
558
559 time(&t);
560 t+=adj;
561 return(ASN1_UTCTIME_set(s,t));
562 }
563
7e258a56 564int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
d02b48c6
RE
565 {
566 EVP_PKEY *ktmp=NULL,*ktmp2;
567 int i,j;
568
569 if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return(1);
570
7e258a56 571 for (i=0; i<sk_X509_num(chain); i++)
d02b48c6 572 {
7e258a56 573 ktmp=X509_get_pubkey(sk_X509_value(chain,i));
d02b48c6
RE
574 if (ktmp == NULL)
575 {
576 X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
577 return(0);
578 }
579 if (!EVP_PKEY_missing_parameters(ktmp))
580 break;
581 else
582 {
cfcf6453 583 EVP_PKEY_free(ktmp);
d02b48c6
RE
584 ktmp=NULL;
585 }
586 }
587 if (ktmp == NULL)
588 {
589 X509err(X509_F_X509_GET_PUBKEY_PARAMETERS,X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
590 return(0);
591 }
592
593 /* first, populate the other certs */
594 for (j=i-1; j >= 0; j--)
595 {
7e258a56 596 ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
d02b48c6 597 EVP_PKEY_copy_parameters(ktmp2,ktmp);
cfcf6453 598 EVP_PKEY_free(ktmp2);
d02b48c6
RE
599 }
600
cfcf6453
DSH
601 if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
602 EVP_PKEY_free(ktmp);
d02b48c6
RE
603 return(1);
604 }
605
6b691a5c 606int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
d02b48c6
RE
607 {
608 X509_OBJECT *obj,*r;
609 int ret=1;
610
611 if (x == NULL) return(0);
612 obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT));
613 if (obj == NULL)
614 {
615 X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE);
616 return(0);
617 }
618 obj->type=X509_LU_X509;
619 obj->data.x509=x;
620
621 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
622
623 X509_OBJECT_up_ref_count(obj);
624
625 r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj);
626 if (r != NULL)
627 { /* oops, put it back */
628 lh_delete(ctx->certs,(char *)obj);
629 X509_OBJECT_free_contents(obj);
630 Free(obj);
631 lh_insert(ctx->certs,(char *)r);
632 X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE);
633 ret=0;
634 }
635
636 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
637
638 return(ret);
639 }
640
6b691a5c 641int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
58964a49
RE
642 {
643 X509_OBJECT *obj,*r;
644 int ret=1;
645
646 if (x == NULL) return(0);
647 obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT));
648 if (obj == NULL)
649 {
650 X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE);
651 return(0);
652 }
653 obj->type=X509_LU_CRL;
654 obj->data.crl=x;
655
656 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
657
658 X509_OBJECT_up_ref_count(obj);
659
660 r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj);
661 if (r != NULL)
662 { /* oops, put it back */
663 lh_delete(ctx->certs,(char *)obj);
664 X509_OBJECT_free_contents(obj);
665 Free(obj);
666 lh_insert(ctx->certs,(char *)r);
667 X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE);
668 ret=0;
669 }
670
671 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
672
673 return(ret);
674 }
675
6b691a5c
UM
676int X509_STORE_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(),
677 int (*dup_func)(), void (*free_func)())
58964a49
RE
678 {
679 x509_store_ctx_num++;
680 return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1,
681 &x509_store_ctx_method,
682 argl,argp,new_func,dup_func,free_func));
683 }
684
6b691a5c 685int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
58964a49
RE
686 {
687 return(CRYPTO_set_ex_data(&ctx->ex_data,idx,data));
688 }
689
6b691a5c 690void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
58964a49
RE
691 {
692 return(CRYPTO_get_ex_data(&ctx->ex_data,idx));
693 }
694
6b691a5c 695int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
58964a49
RE
696 {
697 return(ctx->error);
698 }
699
6b691a5c 700void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
58964a49
RE
701 {
702 ctx->error=err;
703 }
704
6b691a5c 705int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
58964a49
RE
706 {
707 return(ctx->error_depth);
708 }
709
6b691a5c 710X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
58964a49
RE
711 {
712 return(ctx->current_cert);
713 }
714
7e258a56 715STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
58964a49
RE
716 {
717 return(ctx->chain);
718 }
719
6b691a5c 720void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
58964a49
RE
721 {
722 ctx->cert=x;
723 }
724
6b691a5c 725void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
58964a49
RE
726 {
727 ctx->untrusted=sk;
728 }
729
13938ace 730int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
11262391 731 {
13938ace 732 return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
11262391
DSH
733 }
734
13938ace 735void X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
11262391 736 {
13938ace 737 ctx->trust = trust;
11262391
DSH
738 }
739
13938ace
DSH
740/* This function is used to set the X509_STORE_CTX purpose and trust
741 * values. This is intended to be used when another structure has its
742 * own trust and purpose values which (if set) will be inherited by
743 * the ctx. If they aren't set then we will usually have a default
744 * purpose in mind which should then be used to set the trust value.
745 * An example of this is SSL use: an SSL structure will have its own
746 * purpose and trust settings which the application can set: if they
747 * aren't set then we use the default of SSL client/server.
748 */
749
750int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
751 int purpose, int trust)
51630a37 752{
51630a37 753 int idx;
13938ace
DSH
754 /* If purpose not set use default */
755 if(!purpose) purpose = def_purpose;
756 /* If we have a purpose then check it is valid */
757 if(purpose) {
758 idx = X509_PURPOSE_get_by_id(purpose);
759 if(idx == -1) {
760 X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
761 X509_R_UNKNOWN_PURPOSE_ID);
762 return 0;
763 }
764 /* If trust not set then get from purpose default */
765 if(!trust) {
766 X509_PURPOSE *ptmp;
767 ptmp = X509_PURPOSE_iget(idx);
768 trust = ptmp->trust;
769 }
51630a37 770 }
13938ace
DSH
771 if(trust) {
772 idx = X509_TRUST_get_by_id(trust);
773 if(idx == -1) {
774 X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
775 X509_R_UNKNOWN_TRUST_ID);
776 return 0;
777 }
778 }
779
780 if(purpose) ctx->purpose = purpose;
781 if(trust) ctx->trust = trust;
51630a37
DSH
782 return 1;
783}
784
13938ace 785
f73e07cf
BL
786IMPLEMENT_STACK_OF(X509)
787IMPLEMENT_ASN1_SET_OF(X509)
d500de16 788
f73e07cf 789IMPLEMENT_STACK_OF(X509_NAME)
d500de16 790
f5fedc04 791IMPLEMENT_STACK_OF(X509_ATTRIBUTE)
d500de16 792IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)