1*beb6838fSjsg /* $OpenBSD: ocsp_ht.c,v 1.27 2023/11/28 09:29:20 jsg Exp $ */
2e6841c1dSdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
34fcf65c5Sdjm * project 2006.
4da347917Sbeck */
5da347917Sbeck /* ====================================================================
64fcf65c5Sdjm * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7da347917Sbeck *
8da347917Sbeck * Redistribution and use in source and binary forms, with or without
9da347917Sbeck * modification, are permitted provided that the following conditions
10da347917Sbeck * are met:
11da347917Sbeck *
12da347917Sbeck * 1. Redistributions of source code must retain the above copyright
13da347917Sbeck * notice, this list of conditions and the following disclaimer.
14da347917Sbeck *
15da347917Sbeck * 2. Redistributions in binary form must reproduce the above copyright
16da347917Sbeck * notice, this list of conditions and the following disclaimer in
17da347917Sbeck * the documentation and/or other materials provided with the
18da347917Sbeck * distribution.
19da347917Sbeck *
20da347917Sbeck * 3. All advertising materials mentioning features or use of this
21da347917Sbeck * software must display the following acknowledgment:
22da347917Sbeck * "This product includes software developed by the OpenSSL Project
23da347917Sbeck * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24da347917Sbeck *
25da347917Sbeck * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26da347917Sbeck * endorse or promote products derived from this software without
27da347917Sbeck * prior written permission. For written permission, please contact
28da347917Sbeck * licensing@OpenSSL.org.
29da347917Sbeck *
30da347917Sbeck * 5. Products derived from this software may not be called "OpenSSL"
31da347917Sbeck * nor may "OpenSSL" appear in their names without prior written
32da347917Sbeck * permission of the OpenSSL Project.
33da347917Sbeck *
34da347917Sbeck * 6. Redistributions of any form whatsoever must retain the following
35da347917Sbeck * acknowledgment:
36da347917Sbeck * "This product includes software developed by the OpenSSL Project
37da347917Sbeck * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38da347917Sbeck *
39da347917Sbeck * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40da347917Sbeck * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41da347917Sbeck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42da347917Sbeck * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43da347917Sbeck * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44da347917Sbeck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45da347917Sbeck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46da347917Sbeck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47da347917Sbeck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48da347917Sbeck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49da347917Sbeck * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50da347917Sbeck * OF THE POSSIBILITY OF SUCH DAMAGE.
51da347917Sbeck * ====================================================================
52da347917Sbeck *
53da347917Sbeck * This product includes cryptographic software written by Eric Young
54da347917Sbeck * (eay@cryptsoft.com). This product includes software written by Tim
55da347917Sbeck * Hudson (tjh@cryptsoft.com).
56da347917Sbeck *
57da347917Sbeck */
58da347917Sbeck
59da347917Sbeck #include <stdio.h>
60da347917Sbeck #include <stdlib.h>
61da347917Sbeck #include <ctype.h>
62da347917Sbeck #include <string.h>
63e6841c1dSdjm #include <openssl/asn1.h>
64da347917Sbeck #include <openssl/ocsp.h>
65da347917Sbeck #include <openssl/err.h>
66da347917Sbeck #include <openssl/buffer.h>
67da347917Sbeck
684fcf65c5Sdjm /* Stateful OCSP request code, supporting non-blocking I/O */
69da347917Sbeck
704fcf65c5Sdjm /* Opaque OCSP request status structure */
714fcf65c5Sdjm
724fcf65c5Sdjm struct ocsp_req_ctx_st {
734fcf65c5Sdjm int state; /* Current I/O state */
744fcf65c5Sdjm unsigned char *iobuf; /* Line buffer */
754fcf65c5Sdjm int iobuflen; /* Line buffer length */
764fcf65c5Sdjm BIO *io; /* BIO to perform I/O with */
774fcf65c5Sdjm BIO *mem; /* Memory BIO response is built into */
784fcf65c5Sdjm unsigned long asn1_len; /* ASN1 length of response */
794fcf65c5Sdjm };
804fcf65c5Sdjm
814fcf65c5Sdjm #define OCSP_MAX_REQUEST_LENGTH (100 * 1024)
824fcf65c5Sdjm #define OCSP_MAX_LINE_LEN 4096;
834fcf65c5Sdjm
844fcf65c5Sdjm /* OCSP states */
854fcf65c5Sdjm
864fcf65c5Sdjm /* If set no reading should be performed */
874fcf65c5Sdjm #define OHS_NOREAD 0x1000
884fcf65c5Sdjm /* Error condition */
894fcf65c5Sdjm #define OHS_ERROR (0 | OHS_NOREAD)
904fcf65c5Sdjm /* First line being read */
914fcf65c5Sdjm #define OHS_FIRSTLINE 1
924fcf65c5Sdjm /* MIME headers being read */
934fcf65c5Sdjm #define OHS_HEADERS 2
944fcf65c5Sdjm /* OCSP initial header (tag + length) being read */
954fcf65c5Sdjm #define OHS_ASN1_HEADER 3
964fcf65c5Sdjm /* OCSP content octets being read */
974fcf65c5Sdjm #define OHS_ASN1_CONTENT 4
984fcf65c5Sdjm /* Request being sent */
994fcf65c5Sdjm #define OHS_ASN1_WRITE (6 | OHS_NOREAD)
1004fcf65c5Sdjm /* Request being flushed */
1014fcf65c5Sdjm #define OHS_ASN1_FLUSH (7 | OHS_NOREAD)
1024fcf65c5Sdjm /* Completed */
1034fcf65c5Sdjm #define OHS_DONE (8 | OHS_NOREAD)
1044fcf65c5Sdjm
1054fcf65c5Sdjm
1064fcf65c5Sdjm static int parse_http_line1(char *line);
1074fcf65c5Sdjm
1082d2941d0Smiod void
OCSP_REQ_CTX_free(OCSP_REQ_CTX * rctx)1092d2941d0Smiod OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
110da347917Sbeck {
11168a272ffSmiod if (rctx == NULL)
11268a272ffSmiod return;
11368a272ffSmiod
1144fcf65c5Sdjm BIO_free(rctx->mem);
1156f3a6cb1Sbeck free(rctx->iobuf);
1166f3a6cb1Sbeck free(rctx);
1174fcf65c5Sdjm }
118a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_REQ_CTX_free);
119da347917Sbeck
1202d2941d0Smiod int
OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX * rctx,OCSP_REQUEST * req)1212d2941d0Smiod OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req)
1220a5d6edeSdjm {
123dda2f39bSdoug if (BIO_printf(rctx->mem, "Content-Type: application/ocsp-request\r\n"
124dda2f39bSdoug "Content-Length: %d\r\n\r\n", i2d_OCSP_REQUEST(req, NULL)) <= 0)
1250a5d6edeSdjm return 0;
1260a5d6edeSdjm if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0)
1270a5d6edeSdjm return 0;
1280a5d6edeSdjm rctx->state = OHS_ASN1_WRITE;
1290a5d6edeSdjm rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
1300a5d6edeSdjm return 1;
1310a5d6edeSdjm }
132a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_REQ_CTX_set1_req);
1330a5d6edeSdjm
1342d2941d0Smiod int
OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX * rctx,const char * name,const char * value)1352d2941d0Smiod OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, const char *name,
1362d2941d0Smiod const char *value)
1370a5d6edeSdjm {
1380a5d6edeSdjm if (!name)
1390a5d6edeSdjm return 0;
1400a5d6edeSdjm if (BIO_puts(rctx->mem, name) <= 0)
1410a5d6edeSdjm return 0;
1422d2941d0Smiod if (value) {
1430a5d6edeSdjm if (BIO_write(rctx->mem, ": ", 2) != 2)
1440a5d6edeSdjm return 0;
1450a5d6edeSdjm if (BIO_puts(rctx->mem, value) <= 0)
1460a5d6edeSdjm return 0;
1470a5d6edeSdjm }
1480a5d6edeSdjm if (BIO_write(rctx->mem, "\r\n", 2) != 2)
1490a5d6edeSdjm return 0;
1500a5d6edeSdjm return 1;
1510a5d6edeSdjm }
152a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_REQ_CTX_add1_header);
1530a5d6edeSdjm
1542d2941d0Smiod OCSP_REQ_CTX *
OCSP_sendreq_new(BIO * io,const char * path,OCSP_REQUEST * req,int maxline)15514edca61Stb OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, int maxline)
1564fcf65c5Sdjm {
1574fcf65c5Sdjm OCSP_REQ_CTX *rctx;
1582d2941d0Smiod
1596f3a6cb1Sbeck rctx = malloc(sizeof(OCSP_REQ_CTX));
160c9004369Smiod if (rctx == NULL)
161a0f54154Smiod return NULL;
1620a5d6edeSdjm rctx->state = OHS_ERROR;
1637f3aaf75Smiod if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL) {
1647f3aaf75Smiod free(rctx);
1657f3aaf75Smiod return NULL;
1667f3aaf75Smiod }
1674fcf65c5Sdjm rctx->io = io;
1680a5d6edeSdjm rctx->asn1_len = 0;
1694fcf65c5Sdjm if (maxline > 0)
1704fcf65c5Sdjm rctx->iobuflen = maxline;
1714fcf65c5Sdjm else
1724fcf65c5Sdjm rctx->iobuflen = OCSP_MAX_LINE_LEN;
1736f3a6cb1Sbeck rctx->iobuf = malloc(rctx->iobuflen);
17464b5e5f5Sjsg if (!rctx->iobuf) {
175603b910fSjsg BIO_free(rctx->mem);
17664b5e5f5Sjsg free(rctx);
177a0f54154Smiod return NULL;
17864b5e5f5Sjsg }
1794fcf65c5Sdjm if (!path)
1804fcf65c5Sdjm path = "/";
1814fcf65c5Sdjm
182dda2f39bSdoug if (BIO_printf(rctx->mem, "POST %s HTTP/1.0\r\n", path) <= 0) {
18364b5e5f5Sjsg free(rctx->iobuf);
184603b910fSjsg BIO_free(rctx->mem);
18564b5e5f5Sjsg free(rctx);
186a0f54154Smiod return NULL;
18764b5e5f5Sjsg }
1880a5d6edeSdjm
18964b5e5f5Sjsg if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) {
19064b5e5f5Sjsg free(rctx->iobuf);
191603b910fSjsg BIO_free(rctx->mem);
19264b5e5f5Sjsg free(rctx);
193a0f54154Smiod return NULL;
19464b5e5f5Sjsg }
1954fcf65c5Sdjm
1964fcf65c5Sdjm return rctx;
197da347917Sbeck }
198a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_sendreq_new);
1994fcf65c5Sdjm
200da347917Sbeck /* Parse the HTTP response. This will look like this:
201da347917Sbeck * "HTTP/1.0 200 OK". We need to obtain the numeric code and
2023a5f3d0eSmarkus * (optional) informational message.
203da347917Sbeck */
2042d2941d0Smiod static int
parse_http_line1(char * line)2052d2941d0Smiod parse_http_line1(char *line)
2064fcf65c5Sdjm {
2074fcf65c5Sdjm int retcode;
2084fcf65c5Sdjm char *p, *q, *r;
2094fcf65c5Sdjm
2102d2941d0Smiod /* Skip to first white space (passed protocol info) */
2114fcf65c5Sdjm for (p = line; *p && !isspace((unsigned char)*p); p++)
2124fcf65c5Sdjm continue;
2132d2941d0Smiod if (!*p) {
2145067ae9fSbeck OCSPerror(OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
2154fcf65c5Sdjm return 0;
216da347917Sbeck }
2174fcf65c5Sdjm
218da347917Sbeck /* Skip past white space to start of response code */
2194fcf65c5Sdjm while (*p && isspace((unsigned char)*p))
2204fcf65c5Sdjm p++;
2212d2941d0Smiod if (!*p) {
2225067ae9fSbeck OCSPerror(OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
2234fcf65c5Sdjm return 0;
224da347917Sbeck }
2254fcf65c5Sdjm
226da347917Sbeck /* Find end of response code: first whitespace after start of code */
2274fcf65c5Sdjm for (q = p; *q && !isspace((unsigned char)*q); q++)
2284fcf65c5Sdjm continue;
2292d2941d0Smiod if (!*q) {
2305067ae9fSbeck OCSPerror(OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
2314fcf65c5Sdjm return 0;
232da347917Sbeck }
2334fcf65c5Sdjm
234da347917Sbeck /* Set end of response code and start of message */
235da347917Sbeck *q++ = 0;
2364fcf65c5Sdjm
237da347917Sbeck /* Attempt to parse numeric code */
238da347917Sbeck retcode = strtoul(p, &r, 10);
2394fcf65c5Sdjm
2404fcf65c5Sdjm if (*r)
2414fcf65c5Sdjm return 0;
2424fcf65c5Sdjm
243da347917Sbeck /* Skip over any leading white space in message */
2444fcf65c5Sdjm while (*q && isspace((unsigned char)*q))
2454fcf65c5Sdjm q++;
2462d2941d0Smiod if (*q) {
2474fcf65c5Sdjm /* Finally zap any trailing white space in message (include
2484fcf65c5Sdjm * CRLF) */
2494fcf65c5Sdjm
2504fcf65c5Sdjm /* We know q has a non white space character so this is OK */
2514fcf65c5Sdjm for (r = q + strlen(q) - 1; isspace((unsigned char)*r); r--)
2524fcf65c5Sdjm *r = 0;
253da347917Sbeck }
2542d2941d0Smiod if (retcode != 200) {
2555067ae9fSbeck OCSPerror(OCSP_R_SERVER_RESPONSE_ERROR);
2564fcf65c5Sdjm if (!*q)
2570f637b92Sbeck ERR_asprintf_error_data("Code=%s", p);
2584fcf65c5Sdjm else
2590f637b92Sbeck ERR_asprintf_error_data("Code=%s,Reason=%s", p, q);
2604fcf65c5Sdjm return 0;
261da347917Sbeck }
2624fcf65c5Sdjm
2634fcf65c5Sdjm return 1;
264da347917Sbeck }
2654fcf65c5Sdjm
2662d2941d0Smiod int
OCSP_sendreq_nbio(OCSP_RESPONSE ** presp,OCSP_REQ_CTX * rctx)2672d2941d0Smiod OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
2684fcf65c5Sdjm {
2694fcf65c5Sdjm int i, n;
2704fcf65c5Sdjm const unsigned char *p;
2712d2941d0Smiod
2724fcf65c5Sdjm next_io:
2732d2941d0Smiod if (!(rctx->state & OHS_NOREAD)) {
2744fcf65c5Sdjm n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
2754fcf65c5Sdjm
2762d2941d0Smiod if (n <= 0) {
2774fcf65c5Sdjm if (BIO_should_retry(rctx->io))
2784fcf65c5Sdjm return -1;
2794fcf65c5Sdjm return 0;
2804fcf65c5Sdjm }
2814fcf65c5Sdjm
2824fcf65c5Sdjm /* Write data to memory BIO */
2834fcf65c5Sdjm if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
2844fcf65c5Sdjm return 0;
2854fcf65c5Sdjm }
2864fcf65c5Sdjm
2872d2941d0Smiod switch (rctx->state) {
2884fcf65c5Sdjm case OHS_ASN1_WRITE:
2894fcf65c5Sdjm n = BIO_get_mem_data(rctx->mem, &p);
2904fcf65c5Sdjm i = BIO_write(rctx->io,
2914fcf65c5Sdjm p + (n - rctx->asn1_len), rctx->asn1_len);
2922d2941d0Smiod if (i <= 0) {
2934fcf65c5Sdjm if (BIO_should_retry(rctx->io))
2944fcf65c5Sdjm return -1;
2954fcf65c5Sdjm rctx->state = OHS_ERROR;
2964fcf65c5Sdjm return 0;
2974fcf65c5Sdjm }
2984fcf65c5Sdjm
2994fcf65c5Sdjm rctx->asn1_len -= i;
3004fcf65c5Sdjm if (rctx->asn1_len > 0)
3014fcf65c5Sdjm goto next_io;
3024fcf65c5Sdjm
3034fcf65c5Sdjm rctx->state = OHS_ASN1_FLUSH;
3044fcf65c5Sdjm
3054fcf65c5Sdjm (void)BIO_reset(rctx->mem);
3062d2941d0Smiod /* FALLTHROUGH */
3074fcf65c5Sdjm
3084fcf65c5Sdjm case OHS_ASN1_FLUSH:
3094fcf65c5Sdjm i = BIO_flush(rctx->io);
3102d2941d0Smiod if (i > 0) {
3114fcf65c5Sdjm rctx->state = OHS_FIRSTLINE;
3124fcf65c5Sdjm goto next_io;
3134fcf65c5Sdjm }
3144fcf65c5Sdjm
3154fcf65c5Sdjm if (BIO_should_retry(rctx->io))
3164fcf65c5Sdjm return -1;
3174fcf65c5Sdjm
3184fcf65c5Sdjm rctx->state = OHS_ERROR;
3194fcf65c5Sdjm return 0;
3204fcf65c5Sdjm
3214fcf65c5Sdjm case OHS_ERROR:
3224fcf65c5Sdjm return 0;
3234fcf65c5Sdjm
3244fcf65c5Sdjm case OHS_FIRSTLINE:
3254fcf65c5Sdjm case OHS_HEADERS:
3264fcf65c5Sdjm /* Attempt to read a line in */
3274fcf65c5Sdjm next_line:
3284fcf65c5Sdjm /* Due to &%^*$" memory BIO behaviour with BIO_gets we
3294fcf65c5Sdjm * have to check there's a complete line in there before
3304fcf65c5Sdjm * calling BIO_gets or we'll just get a partial read.
3314fcf65c5Sdjm */
3324fcf65c5Sdjm n = BIO_get_mem_data(rctx->mem, &p);
3332d2941d0Smiod if ((n <= 0) || !memchr(p, '\n', n)) {
3342d2941d0Smiod if (n >= rctx->iobuflen) {
3354fcf65c5Sdjm rctx->state = OHS_ERROR;
3364fcf65c5Sdjm return 0;
3374fcf65c5Sdjm }
3384fcf65c5Sdjm goto next_io;
3394fcf65c5Sdjm }
3404fcf65c5Sdjm n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
3412d2941d0Smiod if (n <= 0) {
3424fcf65c5Sdjm if (BIO_should_retry(rctx->mem))
3434fcf65c5Sdjm goto next_io;
3444fcf65c5Sdjm rctx->state = OHS_ERROR;
3454fcf65c5Sdjm return 0;
3464fcf65c5Sdjm }
3474fcf65c5Sdjm
3484fcf65c5Sdjm /* Don't allow excessive lines */
3492d2941d0Smiod if (n == rctx->iobuflen) {
3504fcf65c5Sdjm rctx->state = OHS_ERROR;
3514fcf65c5Sdjm return 0;
3524fcf65c5Sdjm }
3534fcf65c5Sdjm
3544fcf65c5Sdjm /* First line */
3552d2941d0Smiod if (rctx->state == OHS_FIRSTLINE) {
3562d2941d0Smiod if (parse_http_line1((char *)rctx->iobuf)) {
3574fcf65c5Sdjm rctx->state = OHS_HEADERS;
3584fcf65c5Sdjm goto next_line;
3592d2941d0Smiod } else {
3604fcf65c5Sdjm rctx->state = OHS_ERROR;
3614fcf65c5Sdjm return 0;
3624fcf65c5Sdjm }
3632d2941d0Smiod } else {
3644fcf65c5Sdjm /* Look for blank line: end of headers */
3652d2941d0Smiod for (p = rctx->iobuf; *p; p++) {
3664fcf65c5Sdjm if ((*p != '\r') && (*p != '\n'))
3674fcf65c5Sdjm break;
3684fcf65c5Sdjm }
3694fcf65c5Sdjm if (*p)
3704fcf65c5Sdjm goto next_line;
3714fcf65c5Sdjm
3724fcf65c5Sdjm rctx->state = OHS_ASN1_HEADER;
3734fcf65c5Sdjm }
374*beb6838fSjsg /* FALLTHROUGH */
3754fcf65c5Sdjm
3764fcf65c5Sdjm case OHS_ASN1_HEADER:
377c32db552Sdjm /* Now reading ASN1 header: can read at least 2 bytes which
378c32db552Sdjm * is enough for ASN1 SEQUENCE header and either length field
379c32db552Sdjm * or at least the length of the length field.
3804fcf65c5Sdjm */
3814fcf65c5Sdjm n = BIO_get_mem_data(rctx->mem, &p);
382c32db552Sdjm if (n < 2)
3834fcf65c5Sdjm goto next_io;
3844fcf65c5Sdjm
3854fcf65c5Sdjm /* Check it is an ASN1 SEQUENCE */
3862d2941d0Smiod if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
3874fcf65c5Sdjm rctx->state = OHS_ERROR;
3884fcf65c5Sdjm return 0;
3894fcf65c5Sdjm }
3904fcf65c5Sdjm
3914fcf65c5Sdjm /* Check out length field */
3922d2941d0Smiod if (*p & 0x80) {
393c32db552Sdjm /* If MSB set on initial length octet we can now
394c32db552Sdjm * always read 6 octets: make sure we have them.
395c32db552Sdjm */
396c32db552Sdjm if (n < 6)
397c32db552Sdjm goto next_io;
3984fcf65c5Sdjm n = *p & 0x7F;
3994fcf65c5Sdjm /* Not NDEF or excessive length */
4002d2941d0Smiod if (!n || (n > 4)) {
4014fcf65c5Sdjm rctx->state = OHS_ERROR;
4024fcf65c5Sdjm return 0;
4034fcf65c5Sdjm }
4044fcf65c5Sdjm p++;
4054fcf65c5Sdjm rctx->asn1_len = 0;
4062d2941d0Smiod for (i = 0; i < n; i++) {
4074fcf65c5Sdjm rctx->asn1_len <<= 8;
4084fcf65c5Sdjm rctx->asn1_len |= *p++;
4094fcf65c5Sdjm }
4104fcf65c5Sdjm
4112d2941d0Smiod if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) {
4124fcf65c5Sdjm rctx->state = OHS_ERROR;
4134fcf65c5Sdjm return 0;
4144fcf65c5Sdjm }
4154fcf65c5Sdjm
4164fcf65c5Sdjm rctx->asn1_len += n + 2;
4172d2941d0Smiod } else
4184fcf65c5Sdjm rctx->asn1_len = *p + 2;
4194fcf65c5Sdjm
4204fcf65c5Sdjm rctx->state = OHS_ASN1_CONTENT;
4214fcf65c5Sdjm
4222d2941d0Smiod /* FALLTHROUGH */
4234fcf65c5Sdjm
4244fcf65c5Sdjm case OHS_ASN1_CONTENT:
4254fcf65c5Sdjm n = BIO_get_mem_data(rctx->mem, &p);
4264fcf65c5Sdjm if (n < (int)rctx->asn1_len)
4274fcf65c5Sdjm goto next_io;
4284fcf65c5Sdjm
4294fcf65c5Sdjm *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len);
4302d2941d0Smiod if (*presp) {
4314fcf65c5Sdjm rctx->state = OHS_DONE;
4324fcf65c5Sdjm return 1;
4334fcf65c5Sdjm }
4344fcf65c5Sdjm
4354fcf65c5Sdjm rctx->state = OHS_ERROR;
4364fcf65c5Sdjm return 0;
4374fcf65c5Sdjm
4384fcf65c5Sdjm case OHS_DONE:
4394fcf65c5Sdjm return 1;
4404fcf65c5Sdjm }
4414fcf65c5Sdjm
4424fcf65c5Sdjm return 0;
4434fcf65c5Sdjm }
444a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_sendreq_nbio);
4454fcf65c5Sdjm
4464fcf65c5Sdjm /* Blocking OCSP request handler: now a special case of non-blocking I/O */
4472d2941d0Smiod OCSP_RESPONSE *
OCSP_sendreq_bio(BIO * b,const char * path,OCSP_REQUEST * req)44814edca61Stb OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req)
4494fcf65c5Sdjm {
4504fcf65c5Sdjm OCSP_RESPONSE *resp = NULL;
4514fcf65c5Sdjm OCSP_REQ_CTX *ctx;
4524fcf65c5Sdjm int rv;
4534fcf65c5Sdjm
4544fcf65c5Sdjm ctx = OCSP_sendreq_new(b, path, req, -1);
455a0f54154Smiod if (ctx == NULL)
456a0f54154Smiod return NULL;
4574fcf65c5Sdjm
4582d2941d0Smiod do {
4594fcf65c5Sdjm rv = OCSP_sendreq_nbio(&resp, ctx);
4604fcf65c5Sdjm } while ((rv == -1) && BIO_should_retry(b));
4614fcf65c5Sdjm
4624fcf65c5Sdjm OCSP_REQ_CTX_free(ctx);
4634fcf65c5Sdjm
4644fcf65c5Sdjm if (rv)
465da347917Sbeck return resp;
4664fcf65c5Sdjm
4674fcf65c5Sdjm return NULL;
468da347917Sbeck }
469a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_sendreq_bio);
470