1109998Smarkm/* v3_ocsp.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296465Sdelphij * 1999.
5109998Smarkm */
6109998Smarkm/* ====================================================================
7109998Smarkm * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
8109998Smarkm *
9109998Smarkm * Redistribution and use in source and binary forms, with or without
10109998Smarkm * modification, are permitted provided that the following conditions
11109998Smarkm * are met:
12109998Smarkm *
13109998Smarkm * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
15109998Smarkm *
16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
17109998Smarkm *    notice, this list of conditions and the following disclaimer in
18109998Smarkm *    the documentation and/or other materials provided with the
19109998Smarkm *    distribution.
20109998Smarkm *
21109998Smarkm * 3. All advertising materials mentioning features or use of this
22109998Smarkm *    software must display the following acknowledgment:
23109998Smarkm *    "This product includes software developed by the OpenSSL Project
24109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25109998Smarkm *
26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27109998Smarkm *    endorse or promote products derived from this software without
28109998Smarkm *    prior written permission. For written permission, please contact
29109998Smarkm *    licensing@OpenSSL.org.
30109998Smarkm *
31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
32109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
33109998Smarkm *    permission of the OpenSSL Project.
34109998Smarkm *
35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
36109998Smarkm *    acknowledgment:
37109998Smarkm *    "This product includes software developed by the OpenSSL Project
38109998Smarkm *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39109998Smarkm *
40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
52109998Smarkm * ====================================================================
53109998Smarkm *
54109998Smarkm * This product includes cryptographic software written by Eric Young
55109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
56109998Smarkm * Hudson (tjh@cryptsoft.com).
57109998Smarkm *
58109998Smarkm */
59109998Smarkm
60111147Snectar#ifndef OPENSSL_NO_OCSP
61111147Snectar
62296465Sdelphij# include <stdio.h>
63296465Sdelphij# include "cryptlib.h"
64296465Sdelphij# include <openssl/conf.h>
65296465Sdelphij# include <openssl/asn1.h>
66296465Sdelphij# include <openssl/ocsp.h>
67296465Sdelphij# include <openssl/x509v3.h>
68109998Smarkm
69296465Sdelphij/*
70296465Sdelphij * OCSP extensions and a couple of CRL entry extensions
71109998Smarkm */
72109998Smarkm
73296465Sdelphijstatic int i2r_ocsp_crlid(X509V3_EXT_METHOD *method, void *nonce, BIO *out,
74296465Sdelphij                          int indent);
75296465Sdelphijstatic int i2r_ocsp_acutoff(X509V3_EXT_METHOD *method, void *nonce, BIO *out,
76296465Sdelphij                            int indent);
77296465Sdelphijstatic int i2r_object(X509V3_EXT_METHOD *method, void *obj, BIO *out,
78296465Sdelphij                      int indent);
79109998Smarkm
80109998Smarkmstatic void *ocsp_nonce_new(void);
81109998Smarkmstatic int i2d_ocsp_nonce(void *a, unsigned char **pp);
82160814Ssimonstatic void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length);
83109998Smarkmstatic void ocsp_nonce_free(void *a);
84296465Sdelphijstatic int i2r_ocsp_nonce(X509V3_EXT_METHOD *method, void *nonce, BIO *out,
85296465Sdelphij                          int indent);
86109998Smarkm
87296465Sdelphijstatic int i2r_ocsp_nocheck(X509V3_EXT_METHOD *method, void *nocheck,
88296465Sdelphij                            BIO *out, int indent);
89296465Sdelphijstatic void *s2i_ocsp_nocheck(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
90296465Sdelphij                              const char *str);
91296465Sdelphijstatic int i2r_ocsp_serviceloc(X509V3_EXT_METHOD *method, void *in, BIO *bp,
92296465Sdelphij                               int ind);
93109998Smarkm
94167612Ssimonconst X509V3_EXT_METHOD v3_ocsp_crlid = {
95296465Sdelphij    NID_id_pkix_OCSP_CrlID, 0, ASN1_ITEM_ref(OCSP_CRLID),
96296465Sdelphij    0, 0, 0, 0,
97296465Sdelphij    0, 0,
98296465Sdelphij    0, 0,
99296465Sdelphij    i2r_ocsp_crlid, 0,
100296465Sdelphij    NULL
101109998Smarkm};
102109998Smarkm
103167612Ssimonconst X509V3_EXT_METHOD v3_ocsp_acutoff = {
104296465Sdelphij    NID_id_pkix_OCSP_archiveCutoff, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
105296465Sdelphij    0, 0, 0, 0,
106296465Sdelphij    0, 0,
107296465Sdelphij    0, 0,
108296465Sdelphij    i2r_ocsp_acutoff, 0,
109296465Sdelphij    NULL
110109998Smarkm};
111109998Smarkm
112167612Ssimonconst X509V3_EXT_METHOD v3_crl_invdate = {
113296465Sdelphij    NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
114296465Sdelphij    0, 0, 0, 0,
115296465Sdelphij    0, 0,
116296465Sdelphij    0, 0,
117296465Sdelphij    i2r_ocsp_acutoff, 0,
118296465Sdelphij    NULL
119109998Smarkm};
120109998Smarkm
121167612Ssimonconst X509V3_EXT_METHOD v3_crl_hold = {
122296465Sdelphij    NID_hold_instruction_code, 0, ASN1_ITEM_ref(ASN1_OBJECT),
123296465Sdelphij    0, 0, 0, 0,
124296465Sdelphij    0, 0,
125296465Sdelphij    0, 0,
126296465Sdelphij    i2r_object, 0,
127296465Sdelphij    NULL
128109998Smarkm};
129109998Smarkm
130167612Ssimonconst X509V3_EXT_METHOD v3_ocsp_nonce = {
131296465Sdelphij    NID_id_pkix_OCSP_Nonce, 0, NULL,
132296465Sdelphij    ocsp_nonce_new,
133296465Sdelphij    ocsp_nonce_free,
134296465Sdelphij    d2i_ocsp_nonce,
135296465Sdelphij    i2d_ocsp_nonce,
136296465Sdelphij    0, 0,
137296465Sdelphij    0, 0,
138296465Sdelphij    i2r_ocsp_nonce, 0,
139296465Sdelphij    NULL
140109998Smarkm};
141109998Smarkm
142167612Ssimonconst X509V3_EXT_METHOD v3_ocsp_nocheck = {
143296465Sdelphij    NID_id_pkix_OCSP_noCheck, 0, ASN1_ITEM_ref(ASN1_NULL),
144296465Sdelphij    0, 0, 0, 0,
145296465Sdelphij    0, s2i_ocsp_nocheck,
146296465Sdelphij    0, 0,
147296465Sdelphij    i2r_ocsp_nocheck, 0,
148296465Sdelphij    NULL
149109998Smarkm};
150109998Smarkm
151167612Ssimonconst X509V3_EXT_METHOD v3_ocsp_serviceloc = {
152296465Sdelphij    NID_id_pkix_OCSP_serviceLocator, 0, ASN1_ITEM_ref(OCSP_SERVICELOC),
153296465Sdelphij    0, 0, 0, 0,
154296465Sdelphij    0, 0,
155296465Sdelphij    0, 0,
156296465Sdelphij    i2r_ocsp_serviceloc, 0,
157296465Sdelphij    NULL
158109998Smarkm};
159109998Smarkm
160296465Sdelphijstatic int i2r_ocsp_crlid(X509V3_EXT_METHOD *method, void *in, BIO *bp,
161296465Sdelphij                          int ind)
162109998Smarkm{
163296465Sdelphij    OCSP_CRLID *a = in;
164296465Sdelphij    if (a->crlUrl) {
165296465Sdelphij        if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0)
166296465Sdelphij            goto err;
167296465Sdelphij        if (!ASN1_STRING_print(bp, (ASN1_STRING *)a->crlUrl))
168296465Sdelphij            goto err;
169296465Sdelphij        if (BIO_write(bp, "\n", 1) <= 0)
170296465Sdelphij            goto err;
171296465Sdelphij    }
172296465Sdelphij    if (a->crlNum) {
173296465Sdelphij        if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0)
174296465Sdelphij            goto err;
175296465Sdelphij        if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0)
176296465Sdelphij            goto err;
177296465Sdelphij        if (BIO_write(bp, "\n", 1) <= 0)
178296465Sdelphij            goto err;
179296465Sdelphij    }
180296465Sdelphij    if (a->crlTime) {
181296465Sdelphij        if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0)
182296465Sdelphij            goto err;
183296465Sdelphij        if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime))
184296465Sdelphij            goto err;
185296465Sdelphij        if (BIO_write(bp, "\n", 1) <= 0)
186296465Sdelphij            goto err;
187296465Sdelphij    }
188296465Sdelphij    return 1;
189296465Sdelphij err:
190296465Sdelphij    return 0;
191109998Smarkm}
192109998Smarkm
193296465Sdelphijstatic int i2r_ocsp_acutoff(X509V3_EXT_METHOD *method, void *cutoff, BIO *bp,
194296465Sdelphij                            int ind)
195109998Smarkm{
196296465Sdelphij    if (BIO_printf(bp, "%*s", ind, "") <= 0)
197296465Sdelphij        return 0;
198296465Sdelphij    if (!ASN1_GENERALIZEDTIME_print(bp, cutoff))
199296465Sdelphij        return 0;
200296465Sdelphij    return 1;
201109998Smarkm}
202109998Smarkm
203109998Smarkmstatic int i2r_object(X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind)
204109998Smarkm{
205296465Sdelphij    if (BIO_printf(bp, "%*s", ind, "") <= 0)
206296465Sdelphij        return 0;
207296465Sdelphij    if (i2a_ASN1_OBJECT(bp, oid) <= 0)
208296465Sdelphij        return 0;
209296465Sdelphij    return 1;
210109998Smarkm}
211109998Smarkm
212296465Sdelphij/*
213296465Sdelphij * OCSP nonce. This is needs special treatment because it doesn't have an
214296465Sdelphij * ASN1 encoding at all: it just contains arbitrary data.
215109998Smarkm */
216109998Smarkm
217109998Smarkmstatic void *ocsp_nonce_new(void)
218109998Smarkm{
219296465Sdelphij    return ASN1_OCTET_STRING_new();
220109998Smarkm}
221109998Smarkm
222109998Smarkmstatic int i2d_ocsp_nonce(void *a, unsigned char **pp)
223109998Smarkm{
224296465Sdelphij    ASN1_OCTET_STRING *os = a;
225296465Sdelphij    if (pp) {
226296465Sdelphij        memcpy(*pp, os->data, os->length);
227296465Sdelphij        *pp += os->length;
228296465Sdelphij    }
229296465Sdelphij    return os->length;
230109998Smarkm}
231109998Smarkm
232160814Ssimonstatic void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length)
233109998Smarkm{
234296465Sdelphij    ASN1_OCTET_STRING *os, **pos;
235296465Sdelphij    pos = a;
236296465Sdelphij    if (!pos || !*pos)
237296465Sdelphij        os = ASN1_OCTET_STRING_new();
238296465Sdelphij    else
239296465Sdelphij        os = *pos;
240296465Sdelphij    if (!ASN1_OCTET_STRING_set(os, *pp, length))
241296465Sdelphij        goto err;
242109998Smarkm
243296465Sdelphij    *pp += length;
244109998Smarkm
245296465Sdelphij    if (pos)
246296465Sdelphij        *pos = os;
247296465Sdelphij    return os;
248109998Smarkm
249296465Sdelphij err:
250296465Sdelphij    if (os && (!pos || (*pos != os)))
251296465Sdelphij        M_ASN1_OCTET_STRING_free(os);
252296465Sdelphij    OCSPerr(OCSP_F_D2I_OCSP_NONCE, ERR_R_MALLOC_FAILURE);
253296465Sdelphij    return NULL;
254109998Smarkm}
255109998Smarkm
256109998Smarkmstatic void ocsp_nonce_free(void *a)
257109998Smarkm{
258296465Sdelphij    M_ASN1_OCTET_STRING_free(a);
259109998Smarkm}
260109998Smarkm
261296465Sdelphijstatic int i2r_ocsp_nonce(X509V3_EXT_METHOD *method, void *nonce, BIO *out,
262296465Sdelphij                          int indent)
263109998Smarkm{
264296465Sdelphij    if (BIO_printf(out, "%*s", indent, "") <= 0)
265296465Sdelphij        return 0;
266296465Sdelphij    if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0)
267296465Sdelphij        return 0;
268296465Sdelphij    return 1;
269109998Smarkm}
270109998Smarkm
271109998Smarkm/* Nocheck is just a single NULL. Don't print anything and always set it */
272109998Smarkm
273296465Sdelphijstatic int i2r_ocsp_nocheck(X509V3_EXT_METHOD *method, void *nocheck,
274296465Sdelphij                            BIO *out, int indent)
275109998Smarkm{
276296465Sdelphij    return 1;
277109998Smarkm}
278109998Smarkm
279296465Sdelphijstatic void *s2i_ocsp_nocheck(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
280296465Sdelphij                              const char *str)
281109998Smarkm{
282296465Sdelphij    return ASN1_NULL_new();
283109998Smarkm}
284109998Smarkm
285296465Sdelphijstatic int i2r_ocsp_serviceloc(X509V3_EXT_METHOD *method, void *in, BIO *bp,
286296465Sdelphij                               int ind)
287296465Sdelphij{
288296465Sdelphij    int i;
289296465Sdelphij    OCSP_SERVICELOC *a = in;
290296465Sdelphij    ACCESS_DESCRIPTION *ad;
291109998Smarkm
292296465Sdelphij    if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0)
293296465Sdelphij        goto err;
294296465Sdelphij    if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0)
295296465Sdelphij        goto err;
296296465Sdelphij    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) {
297296465Sdelphij        ad = sk_ACCESS_DESCRIPTION_value(a->locator, i);
298296465Sdelphij        if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0)
299296465Sdelphij            goto err;
300296465Sdelphij        if (i2a_ASN1_OBJECT(bp, ad->method) <= 0)
301296465Sdelphij            goto err;
302296465Sdelphij        if (BIO_puts(bp, " - ") <= 0)
303296465Sdelphij            goto err;
304296465Sdelphij        if (GENERAL_NAME_print(bp, ad->location) <= 0)
305296465Sdelphij            goto err;
306296465Sdelphij    }
307296465Sdelphij    return 1;
308296465Sdelphij err:
309296465Sdelphij    return 0;
310296465Sdelphij}
311111147Snectar#endif
312