Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
+ *) Update OCSP API. Remove obsolete extensions argument from
+ various functions. Extensions are now handled using the new
+ OCSP extension code. New simple OCSP HTTP function which
+ can be used to send requests and parse the response.
+ [Steve Henson]
+
*) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new
ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN
uses the special reorder version of SET OF to sort the attributes
cont = *in;
/* If indefinite length constructed find the real end */
if(inf) {
- asn1_collect(NULL, &p, plen, inf, -1, -1);
+ if(!asn1_collect(NULL, &p, plen, inf, -1, -1)) goto err;
len = p - cont;
} else {
len = p - cont + plen;
* internally irrespective of the type. So instead just check
* for UNIVERSAL class and ignore the tag.
*/
- asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL);
- cont = (unsigned char *)buf.data;
+ if(!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL)) goto err;
len = buf.length;
+ /* Append a final null to string */
+ if(!BUF_MEM_grow(&buf, len + 1)) {
+ ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ buf.data[len] = 0;
+ cont = (unsigned char *)buf.data;
free_cont = 1;
} else {
cont = p;
APPS=
LIB=$(TOP)/libcrypto.a
-LIBSRC= ocsp_asn.c ocsp_ext.c \
+LIBSRC= ocsp_asn.c ocsp_ext.c ocsp_ht.c \
ocsp_lib.c ocsp_prn.c ocsp_err.c
-LIBOBJ= ocsp_asn.o ocsp_ext.o \
+LIBOBJ= ocsp_asn.o ocsp_ext.o ocsp_ht.o \
ocsp_lib.o ocsp_prn.o ocsp_err.o
SRC= $(LIBSRC)
(OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
(char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+
OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
X509_NAME *issuerName,
ASN1_BIT_STRING* issuerKey,
OCSP_CERTSTATUS *OCSP_cert_status_new(int status, int reason, char *tim);
-OCSP_REQUEST *OCSP_request_new(X509_NAME* name,
- STACK_OF(X509_EXTENSION) *extensions);
+OCSP_REQUEST *OCSP_request_new(X509_NAME* name);
int OCSP_request_add(OCSP_REQUEST *req,
- OCSP_CERTID *cid,
- STACK_OF(X509_EXTENSION) *extensions);
+ OCSP_CERTID *cid);
int OCSP_request_sign(OCSP_REQUEST *req,
EVP_PKEY *key,
int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey);
OCSP_BASICRESP *OCSP_basic_response_new(int tag,
- X509* cert,
- STACK_OF(X509_EXTENSION) *extensions);
+ X509* cert);
int OCSP_basic_response_add(OCSP_BASICRESP *rsp,
OCSP_CERTID *cid,
OCSP_CERTSTATUS *cst,
char *thisUpdate,
- char *nextUpdate,
- STACK_OF(X509_EXTENSION) *extensions);
+ char *nextUpdate);
int OCSP_basic_response_sign(OCSP_BASICRESP *brsp,
EVP_PKEY *key,
#define OCSP_F_CERT_ID_NEW 102
#define OCSP_F_CERT_STATUS_NEW 103
#define OCSP_F_D2I_OCSP_NONCE 109
+#define OCSP_F_OCSP_SENDREQ_BIO 110
#define OCSP_F_REQUEST_VERIFY 104
#define OCSP_F_RESPONSE_VERIFY 105
#define OCSP_F_S2I_OCSP_NONCE 107
#define OCSP_R_FAILED_TO_STAT 111
#define OCSP_R_MISSING_VALUE 112
#define OCSP_R_NO_CERTIFICATE 102
+#define OCSP_R_NO_CONTENT 115
#define OCSP_R_NO_PUBLIC_KEY 103
#define OCSP_R_NO_RESPONSE_DATA 104
#define OCSP_R_NO_SIGNATURE 105
#define OCSP_R_REVOKED_NO_TIME 106
+#define OCSP_R_SERVER_READ_ERROR 116
+#define OCSP_R_SERVER_RESPONSE_ERROR 117
+#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 118
+#define OCSP_R_SERVER_WRITE_ERROR 119
#define OCSP_R_UNKNOWN_NID 107
#define OCSP_R_UNSUPPORTED_OPTION 113
#define OCSP_R_VALUE_ALREADY 114
-/* ocsp.c */
+/* ocsp_asn.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 2000.
*/
{ERR_PACK(0,OCSP_F_CERT_ID_NEW,0), "CERT_ID_NEW"},
{ERR_PACK(0,OCSP_F_CERT_STATUS_NEW,0), "CERT_STATUS_NEW"},
{ERR_PACK(0,OCSP_F_D2I_OCSP_NONCE,0), "D2I_OCSP_NONCE"},
+{ERR_PACK(0,OCSP_F_OCSP_SENDREQ_BIO,0), "OCSP_sendreq_bio"},
{ERR_PACK(0,OCSP_F_REQUEST_VERIFY,0), "REQUEST_VERIFY"},
{ERR_PACK(0,OCSP_F_RESPONSE_VERIFY,0), "RESPONSE_VERIFY"},
{ERR_PACK(0,OCSP_F_S2I_OCSP_NONCE,0), "S2I_OCSP_NONCE"},
{OCSP_R_FAILED_TO_STAT ,"failed to stat"},
{OCSP_R_MISSING_VALUE ,"missing value"},
{OCSP_R_NO_CERTIFICATE ,"no certificate"},
+{OCSP_R_NO_CONTENT ,"no content"},
{OCSP_R_NO_PUBLIC_KEY ,"no public key"},
{OCSP_R_NO_RESPONSE_DATA ,"no response data"},
{OCSP_R_NO_SIGNATURE ,"no signature"},
{OCSP_R_REVOKED_NO_TIME ,"revoked no time"},
+{OCSP_R_SERVER_READ_ERROR ,"server read error"},
+{OCSP_R_SERVER_RESPONSE_ERROR ,"server response error"},
+{OCSP_R_SERVER_RESPONSE_PARSE_ERROR ,"server response parse error"},
+{OCSP_R_SERVER_WRITE_ERROR ,"server write error"},
{OCSP_R_UNKNOWN_NID ,"unknown nid"},
{OCSP_R_UNSUPPORTED_OPTION ,"unsupported option"},
{OCSP_R_VALUE_ALREADY ,"value already"},
--- /dev/null
+/* ocsp_ht.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/asn1.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <openssl/ocsp.h>
+#include <openssl/err.h>
+#include <openssl/buffer.h>
+
+/* Quick and dirty HTTP OCSP request handler.
+ * Could make this a bit cleverer by adding
+ * support for non blocking BIOs and a few
+ * other refinements.
+ */
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req)
+{
+ BIO *mem = NULL;
+ char tmpbuf[1024];
+ OCSP_RESPONSE *resp = NULL;
+ char *p, *q, *r;
+ int len, retcode;
+ static char req_txt[] =
+"POST %s HTTP/1.0\r\n\
+Content-Type:application/ocsp-request\r\n\
+Content-length: %d\r\n\r\n";
+
+ len = i2d_OCSP_REQUEST(req, NULL);
+ if(BIO_printf(b, req_txt, path, len) < 0) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR);
+ goto err;
+ }
+ if(i2d_OCSP_REQUEST_bio(b, req) <= 0) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR);
+ goto err;
+ }
+ if(!(mem = BIO_new(BIO_s_mem()))) goto err;
+ /* Copy response to a memory BIO: socket bios can't do gets! */
+ while ((len = BIO_read(b, tmpbuf, 1024))) {
+ if(len < 0) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_READ_ERROR);
+ goto err;
+ }
+ BIO_write(mem, tmpbuf, len);
+ }
+ if(BIO_gets(mem, tmpbuf, 512) <= 0) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+ goto err;
+ }
+ /* Parse the HTTP response. This will look like this:
+ * "HTTP/1.0 200 OK". We need to obtain the numeric code and
+ * informational message.
+ */
+
+ /* Skip to first white space (passed protocol info) */
+ for(p = tmpbuf; *p && !isspace(*p); p++) continue;
+ if(!*p) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+ goto err;
+ }
+ /* Skip past white space to start of response code */
+ while(*p && isspace(*p)) p++;
+ if(!*p) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+ goto err;
+ }
+ /* Find end of response code: first whitespace after start of code */
+ for(q = p; *q && !isspace(*q); q++) continue;
+ if(!*q) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+ goto err;
+ }
+ /* Set end of response code and start of message */
+ *q++ = 0;
+ /* Attempt to parse numeric code */
+ retcode = strtoul(p, &r, 10);
+ if(*r) goto err;
+ /* Skip over any leading white space in message */
+ while(*q && isspace(*q)) q++;
+ if(!*q) goto err;
+ /* Finally zap any trailing white space in message (include CRLF) */
+ /* We know q has a non white space character so this is OK */
+ for(r = q + strlen(q) - 1; isspace(*r); r--) *r = 0;
+ if(retcode != 200) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_ERROR);
+ ERR_add_error_data(4, "Code=", p, ",Reason=", q);
+ goto err;
+ }
+ /* Find blank line marking beginning of content */
+ while(BIO_gets(mem, tmpbuf, 512) > 0)
+ {
+ for(p = tmpbuf; *p && isspace(*p); p++) continue;
+ if(!*p) break;
+ }
+ if(*p) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_NO_CONTENT);
+ goto err;
+ }
+ if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) {
+ OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,ERR_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ err:
+ BIO_free(mem);
+ return resp;
+}
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
-#include <openssl/safestack.h>
#include <openssl/ocsp.h>
-static STACK_OF(X509_EXTENSION) *ext_dup(STACK_OF(X509_EXTENSION) *fr)
- {
- int i;
- STACK_OF(X509_EXTENSION) *to = NULL;
-
- if (!(to = sk_X509_EXTENSION_dup(fr)))
- goto err;
- for (i = 0; i < sk_X509_EXTENSION_num(fr); i++)
- {
- sk_X509_EXTENSION_set(to, i,
- X509_EXTENSION_dup(sk_X509_EXTENSION_value(fr, i)));
- if (! sk_X509_EXTENSION_value(to, i))
- goto err;
- }
- return to;
-err:
- if (to) sk_X509_EXTENSION_pop_free(to, X509_EXTENSION_free);
- return NULL;
- }
+/* Convert a certificate and its issuer to an OCSP_CERTID */
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer)
+{
+ X509_NAME *iname;
+ ASN1_INTEGER *serial;
+ ASN1_BIT_STRING *ikey;
+#ifndef NO_SHA1
+ if(!dgst) dgst = EVP_sha1();
+#endif
+ iname = X509_get_issuer_name(subject);
+ serial = X509_get_serialNumber(subject);
+ ikey = issuer->cert_info->key->public_key;
+ return OCSP_cert_id_new(dgst, iname, ikey, serial);
+}
+
OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
X509_NAME *issuerName,
return NULL;
}
-OCSP_REQUEST *OCSP_request_new(X509_NAME* name,
- STACK_OF(X509_EXTENSION) *extensions)
+OCSP_REQUEST *OCSP_request_new(X509_NAME* name)
{
OCSP_REQUEST *req = NULL;
req->tbsRequest->requestorName->d.dirn = X509_NAME_dup(name);
}
if (!(req->tbsRequest->requestList = sk_OCSP_ONEREQ_new(NULL))) goto err;
- if (extensions &&
- (!(req->tbsRequest->requestExtensions = ext_dup(extensions))))
- goto err;
return req;
err:
if (req) OCSP_REQUEST_free(req);
return NULL;
}
-int OCSP_request_add(OCSP_REQUEST *req,
- OCSP_CERTID *cid,
- STACK_OF(X509_EXTENSION) *extensions)
+int OCSP_request_add(OCSP_REQUEST *req, OCSP_CERTID *cid)
{
OCSP_ONEREQ *one = NULL;
if (!(one = OCSP_ONEREQ_new())) goto err;
if (one->reqCert) OCSP_CERTID_free(one->reqCert);
if (!(one->reqCert = OCSP_CERTID_dup(cid))) goto err;
- if (extensions&&(!(one->singleRequestExtensions=ext_dup(extensions))))
- goto err;
if (!sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) goto err;
return 1;
err:
return 0;
}
-OCSP_BASICRESP *OCSP_basic_response_new(int type,
- X509* cert,
- STACK_OF(X509_EXTENSION) *extensions)
+OCSP_BASICRESP *OCSP_basic_response_new(int type, X509* cert)
{
time_t t;
OCSP_RESPID *rid;
if (!(ASN1_GENERALIZEDTIME_set(rsp->tbsResponseData->producedAt, t)))
goto err;
if (!(rsp->tbsResponseData->responses = sk_OCSP_SINGLERESP_new(NULL))) goto err;
- if (extensions && (!(rsp->tbsResponseData->responseExtensions =
- ext_dup(extensions))))
- goto err;
return rsp;
err:
if (rsp) OCSP_BASICRESP_free(rsp);
OCSP_CERTID *cid,
OCSP_CERTSTATUS *cst,
char *this,
- char *next,
- STACK_OF(X509_EXTENSION) *extensions)
+ char *next)
{
OCSP_SINGLERESP *single = NULL;
if (!ASN1_GENERALIZEDTIME_set_string(single->nextUpdate,next))
goto err;
}
- if (extensions && (!(single->singleExtensions = ext_dup(extensions))))
- goto err;
if (!sk_OCSP_SINGLERESP_push(rsp->tbsResponseData->responses,single)) goto err;
return 1;
err:
ASN1_SEQUENCE(DIST_POINT) = {
ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
- ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, distpoint, GENERAL_NAME, 2)
+ ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
} ASN1_SEQUENCE_END(DIST_POINT);
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)