OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
ocsp_ext.c
Go to the documentation of this file.
1 /* ocsp_ext.c */
2 /* Written by Tom Titchener <[email protected]> for the OpenSSL
3  * project. */
4 
5 /* History:
6  This file was transfered to Richard Levitte from CertCo by Kathy
7  Weinhold in mid-spring 2000 to be included in OpenSSL or released
8  as a patch kit. */
9 
10 /* ====================================================================
11  * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. All advertising materials mentioning features or use of this
26  * software must display the following acknowledgment:
27  * "This product includes software developed by the OpenSSL Project
28  * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
29  *
30  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
31  * endorse or promote products derived from this software without
32  * prior written permission. For written permission, please contact
34  *
35  * 5. Products derived from this software may not be called "OpenSSL"
36  * nor may "OpenSSL" appear in their names without prior written
37  * permission of the OpenSSL Project.
38  *
39  * 6. Redistributions of any form whatsoever must retain the following
40  * acknowledgment:
41  * "This product includes software developed by the OpenSSL Project
42  * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
43  *
44  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
45  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
48  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55  * OF THE POSSIBILITY OF SUCH DAMAGE.
56  * ====================================================================
57  *
58  * This product includes cryptographic software written by Eric Young
59  * ([email protected]). This product includes software written by Tim
60  * Hudson ([email protected]).
61  *
62  */
63 
64 #include <stdio.h>
65 #include <cryptlib.h>
66 #include <openssl/objects.h>
67 #include <openssl/x509.h>
68 #include <openssl/ocsp.h>
69 #include <openssl/rand.h>
70 #include <openssl/x509v3.h>
71 
72 /* Standard wrapper functions for extensions */
73 
74 /* OCSP request extensions */
75 
77  {
78  return(X509v3_get_ext_count(x->tbsRequest->requestExtensions));
79  }
80 
81 int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
82  {
83  return(X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions,nid,lastpos));
84  }
85 
87  {
88  return(X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions,obj,lastpos));
89  }
90 
91 int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
92  {
93  return(X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,crit,lastpos));
94  }
95 
97  {
98  return(X509v3_get_ext(x->tbsRequest->requestExtensions,loc));
99  }
100 
102  {
103  return(X509v3_delete_ext(x->tbsRequest->requestExtensions,loc));
104  }
105 
106 void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
107  {
108  return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx);
109  }
110 
111 int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
112  unsigned long flags)
113  {
114  return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, crit, flags);
115  }
116 
118  {
119  return(X509v3_add_ext(&(x->tbsRequest->requestExtensions),ex,loc) != NULL);
120  }
121 
122 /* Single extensions */
123 
125  {
126  return(X509v3_get_ext_count(x->singleRequestExtensions));
127  }
128 
129 int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
130  {
131  return(X509v3_get_ext_by_NID(x->singleRequestExtensions,nid,lastpos));
132  }
133 
135  {
136  return(X509v3_get_ext_by_OBJ(x->singleRequestExtensions,obj,lastpos));
137  }
138 
139 int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
140  {
141  return(X509v3_get_ext_by_critical(x->singleRequestExtensions,crit,lastpos));
142  }
143 
145  {
146  return(X509v3_get_ext(x->singleRequestExtensions,loc));
147  }
148 
150  {
151  return(X509v3_delete_ext(x->singleRequestExtensions,loc));
152  }
153 
154 void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
155  {
156  return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
157  }
158 
159 int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
160  unsigned long flags)
161  {
162  return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, flags);
163  }
164 
166  {
167  return(X509v3_add_ext(&(x->singleRequestExtensions),ex,loc) != NULL);
168  }
169 
170 /* OCSP Basic response */
171 
173  {
174  return(X509v3_get_ext_count(x->tbsResponseData->responseExtensions));
175  }
176 
178  {
179  return(X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,nid,lastpos));
180  }
181 
183  {
184  return(X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,obj,lastpos));
185  }
186 
188  {
189  return(X509v3_get_ext_by_critical(x->tbsResponseData->responseExtensions,crit,lastpos));
190  }
191 
193  {
194  return(X509v3_get_ext(x->tbsResponseData->responseExtensions,loc));
195  }
196 
198  {
199  return(X509v3_delete_ext(x->tbsResponseData->responseExtensions,loc));
200  }
201 
202 void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx)
203  {
204  return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, idx);
205  }
206 
207 int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
208  unsigned long flags)
209  {
210  return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, value, crit, flags);
211  }
212 
214  {
215  return(X509v3_add_ext(&(x->tbsResponseData->responseExtensions),ex,loc) != NULL);
216  }
217 
218 /* OCSP single response extensions */
219 
221  {
222  return(X509v3_get_ext_count(x->singleExtensions));
223  }
224 
226  {
227  return(X509v3_get_ext_by_NID(x->singleExtensions,nid,lastpos));
228  }
229 
231  {
232  return(X509v3_get_ext_by_OBJ(x->singleExtensions,obj,lastpos));
233  }
234 
236  {
237  return(X509v3_get_ext_by_critical(x->singleExtensions,crit,lastpos));
238  }
239 
241  {
242  return(X509v3_get_ext(x->singleExtensions,loc));
243  }
244 
246  {
247  return(X509v3_delete_ext(x->singleExtensions,loc));
248  }
249 
250 void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx)
251  {
252  return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
253  }
254 
255 int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
256  unsigned long flags)
257  {
258  return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
259  }
260 
262  {
263  return(X509v3_add_ext(&(x->singleExtensions),ex,loc) != NULL);
264  }
265 
266 /* also CRL Entry Extensions */
267 #if 0
268 ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
269  void *data, STACK_OF(ASN1_OBJECT) *sk)
270  {
271  int i;
272  unsigned char *p, *b = NULL;
273 
274  if (data)
275  {
276  if ((i=i2d(data,NULL)) <= 0) goto err;
277  if (!(b=p=OPENSSL_malloc((unsigned int)i)))
278  goto err;
279  if (i2d(data, &p) <= 0) goto err;
280  }
281  else if (sk)
282  {
283  if ((i=i2d_ASN1_SET_OF_ASN1_OBJECT(sk,NULL,
284  (I2D_OF(ASN1_OBJECT))i2d,
287  IS_SEQUENCE))<=0) goto err;
288  if (!(b=p=OPENSSL_malloc((unsigned int)i)))
289  goto err;
293  IS_SEQUENCE)<=0) goto err;
294  }
295  else
296  {
298  goto err;
299  }
300  if (!s && !(s = ASN1_STRING_new())) goto err;
301  if (!(ASN1_STRING_set(s, b, i))) goto err;
302  OPENSSL_free(b);
303  return s;
304 err:
305  if (b) OPENSSL_free(b);
306  return NULL;
307  }
308 #endif
309 
310 /* Nonce handling functions */
311 
312 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL
313  * a random nonce will be generated.
314  * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the
315  * nonce, previous versions used the raw nonce.
316  */
317 
318 static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len)
319  {
320  unsigned char *tmpval;
322  int ret = 0;
323  if (len <= 0) len = OCSP_DEFAULT_NONCE_LENGTH;
324  /* Create the OCTET STRING manually by writing out the header and
325  * appending the content octets. This avoids an extra memory allocation
326  * operation in some cases. Applications should *NOT* do this because
327  * it relies on library internals.
328  */
330  os.data = OPENSSL_malloc(os.length);
331  if (os.data == NULL)
332  goto err;
333  tmpval = os.data;
335  if (val)
336  memcpy(tmpval, val, len);
337  else
338  RAND_pseudo_bytes(tmpval, len);
340  &os, 0, X509V3_ADD_REPLACE))
341  goto err;
342  ret = 1;
343  err:
344  if (os.data)
345  OPENSSL_free(os.data);
346  return ret;
347  }
348 
349 
350 /* Add nonce to an OCSP request */
351 
352 int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
353  {
354  return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len);
355  }
356 
357 /* Same as above but for a response */
358 
359 int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
360  {
361  return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, len);
362  }
363 
364 /* Check nonce validity in a request and response.
365  * Return value reflects result:
366  * 1: nonces present and equal.
367  * 2: nonces both absent.
368  * 3: nonce present in response only.
369  * 0: nonces both present and not equal.
370  * -1: nonce in request only.
371  *
372  * For most responders clients can check return > 0.
373  * If responder doesn't handle nonces return != 0 may be
374  * necessary. return == 0 is always an error.
375  */
376 
378  {
379  /*
380  * Since we are only interested in the presence or absence of
381  * the nonce and comparing its value there is no need to use
382  * the X509V3 routines: this way we can avoid them allocating an
383  * ASN1_OCTET_STRING structure for the value which would be
384  * freed immediately anyway.
385  */
386 
387  int req_idx, resp_idx;
388  X509_EXTENSION *req_ext, *resp_ext;
391  /* Check both absent */
392  if((req_idx < 0) && (resp_idx < 0))
393  return 2;
394  /* Check in request only */
395  if((req_idx >= 0) && (resp_idx < 0))
396  return -1;
397  /* Check in response but not request */
398  if((req_idx < 0) && (resp_idx >= 0))
399  return 3;
400  /* Otherwise nonce in request and response so retrieve the extensions */
401  req_ext = OCSP_REQUEST_get_ext(req, req_idx);
402  resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
403  if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value))
404  return 0;
405  return 1;
406  }
407 
408 /* Copy the nonce value (if any) from an OCSP request to
409  * a response.
410  */
411 
413  {
414  X509_EXTENSION *req_ext;
415  int req_idx;
416  /* Check for nonce in request */
418  /* If no nonce that's OK */
419  if (req_idx < 0) return 2;
420  req_ext = OCSP_REQUEST_get_ext(req, req_idx);
421  return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
422  }
423 
424 X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim)
425  {
426  X509_EXTENSION *x = NULL;
427  OCSP_CRLID *cid = NULL;
428 
429  if (!(cid = OCSP_CRLID_new())) goto err;
430  if (url)
431  {
432  if (!(cid->crlUrl = ASN1_IA5STRING_new())) goto err;
433  if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err;
434  }
435  if (n)
436  {
437  if (!(cid->crlNum = ASN1_INTEGER_new())) goto err;
438  if (!(ASN1_INTEGER_set(cid->crlNum, *n))) goto err;
439  }
440  if (tim)
441  {
442  if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) goto err;
443  if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
444  goto err;
445  }
447 err:
448  if (cid) OCSP_CRLID_free(cid);
449  return x;
450  }
451 
452 /* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
454  {
455  int nid;
456  STACK_OF(ASN1_OBJECT) *sk = NULL;
457  ASN1_OBJECT *o = NULL;
458  X509_EXTENSION *x = NULL;
459 
460  if (!(sk = sk_ASN1_OBJECT_new_null())) goto err;
461  while (oids && *oids)
462  {
463  if ((nid=OBJ_txt2nid(*oids))!=NID_undef&&(o=OBJ_nid2obj(nid)))
464  sk_ASN1_OBJECT_push(sk, o);
465  oids++;
466  }
468 err:
470  return x;
471  }
472 
473 /* ArchiveCutoff ::= GeneralizedTime */
475  {
476  X509_EXTENSION *x=NULL;
477  ASN1_GENERALIZEDTIME *gt = NULL;
478 
479  if (!(gt = ASN1_GENERALIZEDTIME_new())) goto err;
480  if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) goto err;
482 err:
483  if (gt) ASN1_GENERALIZEDTIME_free(gt);
484  return x;
485  }
486 
487 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
488  * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This
489  * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
490  */
492  {
493  X509_EXTENSION *x = NULL;
494  ASN1_IA5STRING *ia5 = NULL;
495  OCSP_SERVICELOC *sloc = NULL;
496  ACCESS_DESCRIPTION *ad = NULL;
497 
498  if (!(sloc = OCSP_SERVICELOC_new())) goto err;
499  if (!(sloc->issuer = X509_NAME_dup(issuer))) goto err;
500  if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) goto err;
501  while (urls && *urls)
502  {
503  if (!(ad = ACCESS_DESCRIPTION_new())) goto err;
504  if (!(ad->method=OBJ_nid2obj(NID_ad_OCSP))) goto err;
505  if (!(ad->location = GENERAL_NAME_new())) goto err;
506  if (!(ia5 = ASN1_IA5STRING_new())) goto err;
507  if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) goto err;
508  ad->location->type = GEN_URI;
509  ad->location->d.ia5 = ia5;
510  if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) goto err;
511  urls++;
512  }
514 err:
515  if (sloc) OCSP_SERVICELOC_free(sloc);
516  return x;
517  }
518