mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 12:44:45 +02:00
updates to OCSP
This commit is contained in:
@@ -3837,217 +3837,217 @@ static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
|
||||
|
||||
|
||||
static int DecodeSingleResponse(byte* source,
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
{
|
||||
word32 index = *ioIndex, prevIndex, oid, mpi_len;
|
||||
int length, remainder, qty = 0;
|
||||
mp_int mpi;
|
||||
byte serialTmp[EXTERNAL_SERIAL_SIZE];
|
||||
word32 index = *ioIndex, prevIndex, oid, mpi_len;
|
||||
int length, remainder, qty = 0;
|
||||
mp_int mpi;
|
||||
byte serialTmp[EXTERNAL_SERIAL_SIZE];
|
||||
|
||||
/* Outer wrapper of the SEQUENCE OF Single Responses. */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
remainder = length;
|
||||
/* Outer wrapper of the SEQUENCE OF Single Responses. */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
remainder = length;
|
||||
|
||||
/* First Single Response */
|
||||
while (remainder != 0 && qty < STATUS_LIST_SIZE)
|
||||
{
|
||||
prevIndex = index;
|
||||
/* Wrapper around the Single Response */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* First Single Response */
|
||||
while (remainder != 0 && qty < STATUS_LIST_SIZE)
|
||||
{
|
||||
prevIndex = index;
|
||||
/* Wrapper around the Single Response */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Wrapper around the CertID */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Skip the hash algorithm */
|
||||
if (GetAlgoId(source, &index, &oid, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Skip the hash of CN */
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
/* Skip the hash of the issuer public key */
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
/* Wrapper around the CertID */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Skip the hash algorithm */
|
||||
if (GetAlgoId(source, &index, &oid, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Skip the hash of CN */
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
/* Skip the hash of the issuer public key */
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
|
||||
/* Read the serial number */
|
||||
if (GetInt(&mpi, source, &index, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
mpi_len = mp_unsigned_bin_size(&mpi);
|
||||
if (mpi_len < (int)sizeof(serialTmp)) {
|
||||
if (mp_to_unsigned_bin(&mpi, serialTmp) == MP_OKAY) {
|
||||
if (mpi_len > EXTERNAL_SERIAL_SIZE)
|
||||
mpi_len = EXTERNAL_SERIAL_SIZE;
|
||||
XMEMCPY(resp->certSN[qty], serialTmp, mpi_len);
|
||||
resp->certSNsz[qty] = mpi_len;
|
||||
}
|
||||
}
|
||||
mp_clear(&mpi);
|
||||
/* Read the serial number */
|
||||
if (GetInt(&mpi, source, &index, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
mpi_len = mp_unsigned_bin_size(&mpi);
|
||||
if (mpi_len < (int)sizeof(serialTmp)) {
|
||||
if (mp_to_unsigned_bin(&mpi, serialTmp) == MP_OKAY) {
|
||||
if (mpi_len > EXTERNAL_SERIAL_SIZE)
|
||||
mpi_len = EXTERNAL_SERIAL_SIZE;
|
||||
XMEMCPY(resp->certSN[qty], serialTmp, mpi_len);
|
||||
resp->certSNsz[qty] = mpi_len;
|
||||
}
|
||||
}
|
||||
mp_clear(&mpi);
|
||||
|
||||
/* CertStatus */
|
||||
switch (source[index++])
|
||||
{
|
||||
case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
|
||||
resp->certStatus[qty] = CERT_GOOD;
|
||||
index++;
|
||||
break;
|
||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
|
||||
resp->certStatus[qty] = CERT_REVOKED;
|
||||
GetLength(source, &index, &length, size);
|
||||
index += length;
|
||||
break;
|
||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_UNKNOWN):
|
||||
resp->certStatus[qty] = CERT_UNKNOWN;
|
||||
index++;
|
||||
break;
|
||||
default:
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
/* CertStatus */
|
||||
switch (source[index++])
|
||||
{
|
||||
case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
|
||||
resp->certStatus[qty] = CERT_GOOD;
|
||||
index++;
|
||||
break;
|
||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
|
||||
resp->certStatus[qty] = CERT_REVOKED;
|
||||
GetLength(source, &index, &length, size);
|
||||
index += length;
|
||||
break;
|
||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_UNKNOWN):
|
||||
resp->certStatus[qty] = CERT_UNKNOWN;
|
||||
index++;
|
||||
break;
|
||||
default:
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||
return ASN_PARSE_E;
|
||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
|
||||
remainder = remainder + prevIndex - index;
|
||||
qty++;
|
||||
}
|
||||
resp->certStatusCount = qty;
|
||||
remainder = remainder + prevIndex - index;
|
||||
qty++;
|
||||
}
|
||||
resp->certStatusCount = qty;
|
||||
|
||||
*ioIndex = index;
|
||||
*ioIndex = index;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DecodeResponseData(byte* source,
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
{
|
||||
word32 index = *ioIndex;
|
||||
int length, result;
|
||||
int version;
|
||||
word32 responderId = 0;
|
||||
word32 index = *ioIndex;
|
||||
int length, result;
|
||||
int version;
|
||||
word32 responderId = 0;
|
||||
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
resp->respBegin = index;
|
||||
resp->respLength = length;
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
resp->respBegin = index;
|
||||
resp->respLength = length;
|
||||
|
||||
/* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
|
||||
* item isn't an EXPLICIT[0], then set version to zero and move
|
||||
* onto the next item.
|
||||
*/
|
||||
if (source[index] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
|
||||
{
|
||||
index += 2; /* Eat the value and length */
|
||||
if (GetMyVersion(source, &index, &version) < 0)
|
||||
return ASN_PARSE_E;
|
||||
} else
|
||||
version = 0;
|
||||
/* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
|
||||
* item isn't an EXPLICIT[0], then set version to zero and move
|
||||
* onto the next item.
|
||||
*/
|
||||
if (source[index] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
|
||||
{
|
||||
index += 2; /* Eat the value and length */
|
||||
if (GetMyVersion(source, &index, &version) < 0)
|
||||
return ASN_PARSE_E;
|
||||
} else
|
||||
version = 0;
|
||||
|
||||
responderId = source[index++];
|
||||
if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
|
||||
(responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
|
||||
{
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
else
|
||||
return ASN_PARSE_E;
|
||||
responderId = source[index++];
|
||||
if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
|
||||
(responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
|
||||
{
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
else
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Skip GeneralizedTime */
|
||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
/* Skip GeneralizedTime */
|
||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
|
||||
if (DecodeSingleResponse(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (DecodeSingleResponse(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Skip the extensions */
|
||||
if (source[index++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
||||
{
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
/* Skip the extensions */
|
||||
if (source[index++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
||||
{
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DecodeCerts(byte* source,
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
{
|
||||
word32 index = *ioIndex;
|
||||
if (source[index++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||
{
|
||||
int length;
|
||||
word32 index = *ioIndex;
|
||||
if (source[index++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||
{
|
||||
int length;
|
||||
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
index += length;
|
||||
}
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DecodeBasicOcspResponse(byte* source,
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||
{
|
||||
int length;
|
||||
word32 index = *ioIndex;
|
||||
word32 end_index;
|
||||
int length;
|
||||
word32 index = *ioIndex;
|
||||
word32 end_index;
|
||||
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (index + length > size)
|
||||
return ASN_INPUT_E;
|
||||
end_index = index + length;
|
||||
if (index + length > size)
|
||||
return ASN_INPUT_E;
|
||||
end_index = index + length;
|
||||
|
||||
if (DecodeResponseData(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (DecodeResponseData(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Get the signature algorithm */
|
||||
if (GetAlgoId(source, &index, &resp->sigOID, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Get the signature algorithm */
|
||||
if (GetAlgoId(source, &index, &resp->sigOID, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Obtain pointer to the start of the signature, and save the size */
|
||||
if (source[index++] == ASN_BIT_STRING)
|
||||
{
|
||||
int sigLength = 0;
|
||||
if (GetLength(source, &index, &sigLength, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
resp->sigLength = sigLength;
|
||||
resp->sigIndex = index;
|
||||
index += sigLength;
|
||||
}
|
||||
/* Obtain pointer to the start of the signature, and save the size */
|
||||
if (source[index++] == ASN_BIT_STRING)
|
||||
{
|
||||
int sigLength = 0;
|
||||
if (GetLength(source, &index, &sigLength, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
resp->sigLength = sigLength;
|
||||
resp->sigIndex = index;
|
||||
index += sigLength;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the length of the BasicOcspResponse against the current index to
|
||||
* see if there are certificates, they are optional.
|
||||
*/
|
||||
if (index < end_index)
|
||||
return DecodeCerts(source, &index, resp, size);
|
||||
/*
|
||||
* Check the length of the BasicOcspResponse against the current index to
|
||||
* see if there are certificates, they are optional.
|
||||
*/
|
||||
if (index < end_index)
|
||||
return DecodeCerts(source, &index, resp, size);
|
||||
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
*ioIndex = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void InitOcspResponse(OcspResponse* resp, byte* source, word32 inSz, void* heap)
|
||||
{
|
||||
XMEMSET(resp, 0, sizeof(*resp));
|
||||
XMEMSET(resp, 0, sizeof(*resp));
|
||||
resp->source = source;
|
||||
resp->maxIdx = inSz;
|
||||
resp->heap = heap;
|
||||
@@ -4059,55 +4059,67 @@ void FreeOcspResponse(OcspResponse* resp) {}
|
||||
|
||||
int OcspResponseDecode(OcspResponse* resp)
|
||||
{
|
||||
int length = 0;
|
||||
word32 index = 0;
|
||||
byte* source = resp->source;
|
||||
word32 size = resp->maxIdx;
|
||||
word32 oid;
|
||||
int length = 0;
|
||||
word32 index = 0;
|
||||
byte* source = resp->source;
|
||||
word32 size = resp->maxIdx;
|
||||
word32 oid;
|
||||
|
||||
/* peel the outer SEQUENCE wrapper */
|
||||
/* peel the outer SEQUENCE wrapper */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* First get the responseStatus, an ENUMERATED */
|
||||
if (GetEnumerated(source, &index, &resp->responseStatus) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* First get the responseStatus, an ENUMERATED */
|
||||
if (GetEnumerated(source, &index, &resp->responseStatus) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (resp->responseStatus != OCSP_SUCCESSFUL)
|
||||
return 0;
|
||||
if (resp->responseStatus != OCSP_SUCCESSFUL)
|
||||
return 0;
|
||||
|
||||
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
|
||||
if (index >= size)
|
||||
return ASN_INPUT_E;
|
||||
if (source[index++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
|
||||
if (index >= size)
|
||||
return ASN_INPUT_E;
|
||||
if (source[index++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Get the responseBytes SEQUENCE */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
/* Get the responseBytes SEQUENCE */
|
||||
if (GetSequence(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
/* Check ObjectID for the resposeBytes */
|
||||
if (GetObjectId(source, &index, &oid, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (oid != OCSP_BASIC_OID)
|
||||
return ASN_PARSE_E;
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
/* Check ObjectID for the resposeBytes */
|
||||
if (GetObjectId(source, &index, &oid, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (oid != OCSP_BASIC_OID)
|
||||
return ASN_PARSE_E;
|
||||
if (source[index++] != ASN_OCTET_STRING)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (GetLength(source, &index, &length, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (DecodeBasicOcspResponse(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
if (DecodeBasicOcspResponse(source, &index, resp, size) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void InitOcspRequest(OcspRequest* req)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int MakeOcspRequest(OcspRequest* req)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int EncodeOcspRequest(void)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -333,6 +333,14 @@ enum Ocsp_Sums {
|
||||
|
||||
|
||||
typedef struct OcspResponse OcspResponse;
|
||||
typedef struct OcspRequest OcspRequest;
|
||||
|
||||
|
||||
struct OcspRequest {
|
||||
byte* serialNumber; /* not owned by us */
|
||||
int serialSz;
|
||||
};
|
||||
|
||||
|
||||
struct OcspResponse {
|
||||
int responseStatus; /* return code from Responder */
|
||||
|
@@ -40,6 +40,9 @@
|
||||
#ifndef NO_SHA256
|
||||
#include <cyassl/ctaocrypt/sha256.h>
|
||||
#endif
|
||||
#ifdef HAVE_OCSP
|
||||
#include <cyassl/ocsp.h>
|
||||
#endif
|
||||
|
||||
#ifdef CYASSL_CALLBACKS
|
||||
#include <cyassl/openssl/cyassl_callbacks.h>
|
||||
@@ -642,6 +645,9 @@ struct CYASSL_CTX {
|
||||
pem_password_cb passwd_cb;
|
||||
void* userdata;
|
||||
#endif /* OPENSSL_EXTRA */
|
||||
#ifdef HAVE_OCSP
|
||||
CYASSL_OCSP ocsp;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
71
cyassl/ocsp.h
Normal file
71
cyassl/ocsp.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ssl.h
|
||||
*
|
||||
* Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
|
||||
*
|
||||
* This file is part of CyaSSL.
|
||||
*
|
||||
* CyaSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CyaSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
/* CyaSSL OCSP API */
|
||||
|
||||
#ifndef CYASSL_OCSP_H
|
||||
#define CYASSL_OCSP_H
|
||||
|
||||
|
||||
#include <cyassl/ctaocrypt/asn.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct CYASSL_OCSP CYASSL_OCSP;
|
||||
typedef struct CertStatus CertStatus;
|
||||
|
||||
struct CertStatus {
|
||||
byte subjectHash[SHA_SIZE];
|
||||
byte issuerHash[SHA_SIZE];
|
||||
byte serial[EXTERNAL_SERIAL_SIZE];
|
||||
int serialSz;
|
||||
int status;
|
||||
};
|
||||
|
||||
struct CYASSL_OCSP {
|
||||
byte enabled;
|
||||
byte useOverrideUrl;
|
||||
char overrideName[80];
|
||||
int overridePort;
|
||||
int statusLen;
|
||||
CertStatus status[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
CYASSL_LOCAL int CyaSSL_OCSP_Init(CYASSL_OCSP*);
|
||||
CYASSL_LOCAL void CyaSSL_OCSP_Cleanup(CYASSL_OCSP*);
|
||||
CYASSL_LOCAL int CyaSSL_OCSP_set_override_url(CYASSL_OCSP*, const char*);
|
||||
CYASSL_LOCAL int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP*, DecodedCert*);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* CYASSL_OCSP_H */
|
||||
|
||||
|
@@ -508,7 +508,7 @@ CYASSL_API void CyaSSL_ERR_print_errors_fp(FILE*, int err);
|
||||
enum { /* ssl Constants */
|
||||
SSL_ERROR_NONE = 0, /* for most functions */
|
||||
SSL_FAILURE = 0, /* for some functions */
|
||||
SSL_SUCCESS = 1,
|
||||
SSL_SUCCESS = 1,
|
||||
|
||||
SSL_BAD_CERTTYPE = -8,
|
||||
SSL_BAD_STAT = -7,
|
||||
@@ -794,6 +794,13 @@ CYASSL_API int CyaSSL_accept_ex(CYASSL*, HandShakeCallBack, TimeoutCallBack,
|
||||
#endif /* CYASSL_CALLBACKS */
|
||||
|
||||
|
||||
CYASSL_API long CyaSSL_CTX_OCSP_set_options(CYASSL_CTX*, long);
|
||||
CYASSL_API int CyaSSL_CTX_OCSP_set_override_url(CYASSL_CTX*, const char*);
|
||||
|
||||
/* OCSP Options */
|
||||
#define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */
|
||||
#define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
|
||||
* in certificate */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -388,6 +388,9 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
||||
ctx->sendVerify = 0;
|
||||
ctx->quietShutdown = 0;
|
||||
ctx->groupMessages = 0;
|
||||
#ifdef HAVE_OCSP
|
||||
CyaSSL_OCSP_Init(&ctx->ocsp);
|
||||
#endif
|
||||
|
||||
if (InitMutex(&ctx->countMutex) < 0) {
|
||||
CYASSL_MSG("Mutex error on CTX init");
|
||||
@@ -408,6 +411,10 @@ void SSL_CtxResourceFree(CYASSL_CTX* ctx)
|
||||
XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
|
||||
|
||||
FreeSigners(ctx->caList, ctx->heap);
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
CyaSSL_OCSP_Cleanup(&ctx->ocsp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1624,6 +1631,10 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
CyaSSL_OCSP_Lookup_Cert(&ssl->ctx->ocsp, &dCert);
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
/* set X509 format for peer cert even if fatal */
|
||||
XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
|
||||
|
109
src/ocsp.c
109
src/ocsp.c
@@ -24,12 +24,117 @@
|
||||
#endif
|
||||
|
||||
#include <cyassl/error.h>
|
||||
#include <cyassl/ctaocrypt/asn.h>
|
||||
#include <cyassl/ocsp.h>
|
||||
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
CYASSL_API int ocsp_test(unsigned char* buf, int sz);
|
||||
#define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */
|
||||
#define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
|
||||
* in certificate */
|
||||
|
||||
|
||||
int ocsp_test(unsigned char* buf, int sz)
|
||||
{
|
||||
CYASSL_OCSP ocsp;
|
||||
OcspResponse resp;
|
||||
int result;
|
||||
|
||||
CyaSSL_OCSP_Init(&ocsp);
|
||||
InitOcspResponse(&resp, buf, sz, NULL);
|
||||
|
||||
ocsp.enabled = 1;
|
||||
ocsp.useOverrideUrl = 1;
|
||||
CyaSSL_OCSP_set_override_url(&ocsp, "http://ocsp.example.com:8080/");
|
||||
CyaSSL_OCSP_Lookup_Cert(&ocsp, NULL);
|
||||
|
||||
result = OcspResponseDecode(&resp);
|
||||
|
||||
FreeOcspResponse(&resp);
|
||||
CyaSSL_OCSP_Cleanup(&ocsp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
|
||||
{
|
||||
if (ocsp != NULL) {
|
||||
XMEMSET(ocsp, 0, sizeof(*ocsp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp)
|
||||
{
|
||||
ocsp->enabled = 0;
|
||||
/* Deallocate memory */
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url)
|
||||
{
|
||||
if (ocsp != NULL && url != NULL) {
|
||||
int i, cur, hostname;
|
||||
|
||||
/* need to break the url down into scheme, address, and port */
|
||||
/* "http://example.com:8080/" */
|
||||
if (XSTRNCMP(url, "http://", 7) == 0) {
|
||||
cur = 7;
|
||||
} else cur = 0;
|
||||
|
||||
i = 0;
|
||||
while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') {
|
||||
ocsp->overrideName[i++] = url[cur++];
|
||||
}
|
||||
ocsp->overrideName[i] = 0;
|
||||
|
||||
if (url[cur] == ':') {
|
||||
char port[6];
|
||||
int j;
|
||||
i = 0;
|
||||
cur++;
|
||||
while (url[cur] != 0 && url[cur] != '/' && i < 6) {
|
||||
port[i++] = url[cur++];
|
||||
}
|
||||
|
||||
ocsp->overridePort = 0;
|
||||
for (j = 0; j < i; j++) {
|
||||
if (port[j] < '0' || port[j] > '9') return -1;
|
||||
ocsp->overridePort =
|
||||
(ocsp->overridePort * 10) + (port[j] - '0');
|
||||
}
|
||||
}
|
||||
else
|
||||
ocsp->overridePort = 80;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
|
||||
{
|
||||
/* If OCSP lookups are disabled, return success. */
|
||||
if (!ocsp->enabled) return 1;
|
||||
|
||||
/* If OCSP lookups are enabled, but URL Override is disabled, return
|
||||
** a failure. Need to have an override URL for right now. */
|
||||
if (!ocsp->useOverrideUrl || cert == NULL) return 0;
|
||||
|
||||
XMEMCPY(ocsp->status[0].subjectHash, cert->subjectHash, SHA_SIZE);
|
||||
XMEMCPY(ocsp->status[0].issuerHash, cert->issuerHash, SHA_SIZE);
|
||||
XMEMCPY(ocsp->status[0].serial, cert->serial, cert->serialSz);
|
||||
ocsp->status[0].serialSz = cert->serialSz;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ocsp_stub(void) {}
|
||||
|
||||
#endif /* HAVE_OCSP */
|
||||
|
||||
|
23
src/ssl.c
23
src/ssl.c
@@ -5379,3 +5379,26 @@ const byte* CyaSSL_get_sessionID(const CYASSL_SESSION* session)
|
||||
|
||||
#endif /* SESSION_CERTS */
|
||||
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
|
||||
long CyaSSL_CTX_OCSP_set_options(CYASSL_CTX* ctx, long options)
|
||||
{
|
||||
CYASSL_ENTER("CyaSSL_CTX_OCSP_set_options");
|
||||
if (ctx != NULL) {
|
||||
ctx->ocsp.enabled = (options && CYASSL_OCSP_ENABLE) != 0;
|
||||
ctx->ocsp.useOverrideUrl = (options && CYASSL_OCSP_URL_OVERRIDE) != 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_CTX_OCSP_set_override_url(CYASSL_CTX* ctx, const char* url)
|
||||
{
|
||||
CYASSL_ENTER("CyaSSL_CTX_OCSP_set_override_url");
|
||||
return CyaSSL_OCSP_set_override_url(&ctx->ocsp, url);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user