mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 20:54:41 +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,
|
static int DecodeSingleResponse(byte* source,
|
||||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||||
{
|
{
|
||||||
word32 index = *ioIndex, prevIndex, oid, mpi_len;
|
word32 index = *ioIndex, prevIndex, oid, mpi_len;
|
||||||
int length, remainder, qty = 0;
|
int length, remainder, qty = 0;
|
||||||
mp_int mpi;
|
mp_int mpi;
|
||||||
byte serialTmp[EXTERNAL_SERIAL_SIZE];
|
byte serialTmp[EXTERNAL_SERIAL_SIZE];
|
||||||
|
|
||||||
/* Outer wrapper of the SEQUENCE OF Single Responses. */
|
/* Outer wrapper of the SEQUENCE OF Single Responses. */
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
remainder = length;
|
remainder = length;
|
||||||
|
|
||||||
/* First Single Response */
|
/* First Single Response */
|
||||||
while (remainder != 0 && qty < STATUS_LIST_SIZE)
|
while (remainder != 0 && qty < STATUS_LIST_SIZE)
|
||||||
{
|
{
|
||||||
prevIndex = index;
|
prevIndex = index;
|
||||||
/* Wrapper around the Single Response */
|
/* Wrapper around the Single Response */
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Wrapper around the CertID */
|
/* Wrapper around the CertID */
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
/* Skip the hash algorithm */
|
/* Skip the hash algorithm */
|
||||||
if (GetAlgoId(source, &index, &oid, size) < 0)
|
if (GetAlgoId(source, &index, &oid, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
/* Skip the hash of CN */
|
/* Skip the hash of CN */
|
||||||
if (source[index++] != ASN_OCTET_STRING)
|
if (source[index++] != ASN_OCTET_STRING)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
/* Skip the hash of the issuer public key */
|
/* Skip the hash of the issuer public key */
|
||||||
if (source[index++] != ASN_OCTET_STRING)
|
if (source[index++] != ASN_OCTET_STRING)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
|
|
||||||
/* Read the serial number */
|
/* Read the serial number */
|
||||||
if (GetInt(&mpi, source, &index, size) < 0)
|
if (GetInt(&mpi, source, &index, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
mpi_len = mp_unsigned_bin_size(&mpi);
|
mpi_len = mp_unsigned_bin_size(&mpi);
|
||||||
if (mpi_len < (int)sizeof(serialTmp)) {
|
if (mpi_len < (int)sizeof(serialTmp)) {
|
||||||
if (mp_to_unsigned_bin(&mpi, serialTmp) == MP_OKAY) {
|
if (mp_to_unsigned_bin(&mpi, serialTmp) == MP_OKAY) {
|
||||||
if (mpi_len > EXTERNAL_SERIAL_SIZE)
|
if (mpi_len > EXTERNAL_SERIAL_SIZE)
|
||||||
mpi_len = EXTERNAL_SERIAL_SIZE;
|
mpi_len = EXTERNAL_SERIAL_SIZE;
|
||||||
XMEMCPY(resp->certSN[qty], serialTmp, mpi_len);
|
XMEMCPY(resp->certSN[qty], serialTmp, mpi_len);
|
||||||
resp->certSNsz[qty] = mpi_len;
|
resp->certSNsz[qty] = mpi_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp_clear(&mpi);
|
mp_clear(&mpi);
|
||||||
|
|
||||||
/* CertStatus */
|
/* CertStatus */
|
||||||
switch (source[index++])
|
switch (source[index++])
|
||||||
{
|
{
|
||||||
case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
|
case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
|
||||||
resp->certStatus[qty] = CERT_GOOD;
|
resp->certStatus[qty] = CERT_GOOD;
|
||||||
index++;
|
index++;
|
||||||
break;
|
break;
|
||||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
|
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
|
||||||
resp->certStatus[qty] = CERT_REVOKED;
|
resp->certStatus[qty] = CERT_REVOKED;
|
||||||
GetLength(source, &index, &length, size);
|
GetLength(source, &index, &length, size);
|
||||||
index += length;
|
index += length;
|
||||||
break;
|
break;
|
||||||
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_UNKNOWN):
|
case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_UNKNOWN):
|
||||||
resp->certStatus[qty] = CERT_UNKNOWN;
|
resp->certStatus[qty] = CERT_UNKNOWN;
|
||||||
index++;
|
index++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
|
|
||||||
remainder = remainder + prevIndex - index;
|
remainder = remainder + prevIndex - index;
|
||||||
qty++;
|
qty++;
|
||||||
}
|
}
|
||||||
resp->certStatusCount = qty;
|
resp->certStatusCount = qty;
|
||||||
|
|
||||||
*ioIndex = index;
|
*ioIndex = index;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeResponseData(byte* source,
|
static int DecodeResponseData(byte* source,
|
||||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||||
{
|
{
|
||||||
word32 index = *ioIndex;
|
word32 index = *ioIndex;
|
||||||
int length, result;
|
int length, result;
|
||||||
int version;
|
int version;
|
||||||
word32 responderId = 0;
|
word32 responderId = 0;
|
||||||
|
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
resp->respBegin = index;
|
resp->respBegin = index;
|
||||||
resp->respLength = length;
|
resp->respLength = length;
|
||||||
|
|
||||||
/* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
|
/* 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
|
* item isn't an EXPLICIT[0], then set version to zero and move
|
||||||
* onto the next item.
|
* onto the next item.
|
||||||
*/
|
*/
|
||||||
if (source[index] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
|
if (source[index] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
|
||||||
{
|
{
|
||||||
index += 2; /* Eat the value and length */
|
index += 2; /* Eat the value and length */
|
||||||
if (GetMyVersion(source, &index, &version) < 0)
|
if (GetMyVersion(source, &index, &version) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
} else
|
} else
|
||||||
version = 0;
|
version = 0;
|
||||||
|
|
||||||
responderId = source[index++];
|
responderId = source[index++];
|
||||||
if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
|
if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
|
||||||
(responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
|
(responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
|
||||||
{
|
{
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Skip GeneralizedTime */
|
/* Skip GeneralizedTime */
|
||||||
if (source[index++] != ASN_GENERALIZED_TIME)
|
if (source[index++] != ASN_GENERALIZED_TIME)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
|
|
||||||
if (DecodeSingleResponse(source, &index, resp, size) < 0)
|
if (DecodeSingleResponse(source, &index, resp, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Skip the extensions */
|
/* Skip the extensions */
|
||||||
if (source[index++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
if (source[index++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
||||||
{
|
{
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ioIndex = index;
|
*ioIndex = index;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeCerts(byte* source,
|
static int DecodeCerts(byte* source,
|
||||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||||
{
|
{
|
||||||
word32 index = *ioIndex;
|
word32 index = *ioIndex;
|
||||||
if (source[index++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
if (source[index++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
index += length;
|
index += length;
|
||||||
}
|
}
|
||||||
*ioIndex = index;
|
*ioIndex = index;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodeBasicOcspResponse(byte* source,
|
static int DecodeBasicOcspResponse(byte* source,
|
||||||
word32* ioIndex, OcspResponse* resp, word32 size)
|
word32* ioIndex, OcspResponse* resp, word32 size)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
word32 index = *ioIndex;
|
word32 index = *ioIndex;
|
||||||
word32 end_index;
|
word32 end_index;
|
||||||
|
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (index + length > size)
|
if (index + length > size)
|
||||||
return ASN_INPUT_E;
|
return ASN_INPUT_E;
|
||||||
end_index = index + length;
|
end_index = index + length;
|
||||||
|
|
||||||
if (DecodeResponseData(source, &index, resp, size) < 0)
|
if (DecodeResponseData(source, &index, resp, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Get the signature algorithm */
|
/* Get the signature algorithm */
|
||||||
if (GetAlgoId(source, &index, &resp->sigOID, size) < 0)
|
if (GetAlgoId(source, &index, &resp->sigOID, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Obtain pointer to the start of the signature, and save the size */
|
/* Obtain pointer to the start of the signature, and save the size */
|
||||||
if (source[index++] == ASN_BIT_STRING)
|
if (source[index++] == ASN_BIT_STRING)
|
||||||
{
|
{
|
||||||
int sigLength = 0;
|
int sigLength = 0;
|
||||||
if (GetLength(source, &index, &sigLength, size) < 0)
|
if (GetLength(source, &index, &sigLength, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
resp->sigLength = sigLength;
|
resp->sigLength = sigLength;
|
||||||
resp->sigIndex = index;
|
resp->sigIndex = index;
|
||||||
index += sigLength;
|
index += sigLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the length of the BasicOcspResponse against the current index to
|
* Check the length of the BasicOcspResponse against the current index to
|
||||||
* see if there are certificates, they are optional.
|
* see if there are certificates, they are optional.
|
||||||
*/
|
*/
|
||||||
if (index < end_index)
|
if (index < end_index)
|
||||||
return DecodeCerts(source, &index, resp, size);
|
return DecodeCerts(source, &index, resp, size);
|
||||||
|
|
||||||
*ioIndex = index;
|
*ioIndex = index;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InitOcspResponse(OcspResponse* resp, byte* source, word32 inSz, void* heap)
|
void InitOcspResponse(OcspResponse* resp, byte* source, word32 inSz, void* heap)
|
||||||
{
|
{
|
||||||
XMEMSET(resp, 0, sizeof(*resp));
|
XMEMSET(resp, 0, sizeof(*resp));
|
||||||
resp->source = source;
|
resp->source = source;
|
||||||
resp->maxIdx = inSz;
|
resp->maxIdx = inSz;
|
||||||
resp->heap = heap;
|
resp->heap = heap;
|
||||||
@@ -4059,55 +4059,67 @@ void FreeOcspResponse(OcspResponse* resp) {}
|
|||||||
|
|
||||||
int OcspResponseDecode(OcspResponse* resp)
|
int OcspResponseDecode(OcspResponse* resp)
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = 0;
|
||||||
word32 index = 0;
|
word32 index = 0;
|
||||||
byte* source = resp->source;
|
byte* source = resp->source;
|
||||||
word32 size = resp->maxIdx;
|
word32 size = resp->maxIdx;
|
||||||
word32 oid;
|
word32 oid;
|
||||||
|
|
||||||
/* peel the outer SEQUENCE wrapper */
|
/* peel the outer SEQUENCE wrapper */
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* First get the responseStatus, an ENUMERATED */
|
/* First get the responseStatus, an ENUMERATED */
|
||||||
if (GetEnumerated(source, &index, &resp->responseStatus) < 0)
|
if (GetEnumerated(source, &index, &resp->responseStatus) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (resp->responseStatus != OCSP_SUCCESSFUL)
|
if (resp->responseStatus != OCSP_SUCCESSFUL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
|
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
|
||||||
if (index >= size)
|
if (index >= size)
|
||||||
return ASN_INPUT_E;
|
return ASN_INPUT_E;
|
||||||
if (source[index++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
if (source[index++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Get the responseBytes SEQUENCE */
|
/* Get the responseBytes SEQUENCE */
|
||||||
if (GetSequence(source, &index, &length, size) < 0)
|
if (GetSequence(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Check ObjectID for the resposeBytes */
|
/* Check ObjectID for the resposeBytes */
|
||||||
if (GetObjectId(source, &index, &oid, size) < 0)
|
if (GetObjectId(source, &index, &oid, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (oid != OCSP_BASIC_OID)
|
if (oid != OCSP_BASIC_OID)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (source[index++] != ASN_OCTET_STRING)
|
if (source[index++] != ASN_OCTET_STRING)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (GetLength(source, &index, &length, size) < 0)
|
if (GetLength(source, &index, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (DecodeBasicOcspResponse(source, &index, resp, size) < 0)
|
if (DecodeBasicOcspResponse(source, &index, resp, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InitOcspRequest(OcspRequest* req)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MakeOcspRequest(OcspRequest* req)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int EncodeOcspRequest(void)
|
int EncodeOcspRequest(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -333,6 +333,14 @@ enum Ocsp_Sums {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct OcspResponse OcspResponse;
|
typedef struct OcspResponse OcspResponse;
|
||||||
|
typedef struct OcspRequest OcspRequest;
|
||||||
|
|
||||||
|
|
||||||
|
struct OcspRequest {
|
||||||
|
byte* serialNumber; /* not owned by us */
|
||||||
|
int serialSz;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct OcspResponse {
|
struct OcspResponse {
|
||||||
int responseStatus; /* return code from Responder */
|
int responseStatus; /* return code from Responder */
|
||||||
|
@@ -40,6 +40,9 @@
|
|||||||
#ifndef NO_SHA256
|
#ifndef NO_SHA256
|
||||||
#include <cyassl/ctaocrypt/sha256.h>
|
#include <cyassl/ctaocrypt/sha256.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_OCSP
|
||||||
|
#include <cyassl/ocsp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CYASSL_CALLBACKS
|
#ifdef CYASSL_CALLBACKS
|
||||||
#include <cyassl/openssl/cyassl_callbacks.h>
|
#include <cyassl/openssl/cyassl_callbacks.h>
|
||||||
@@ -642,6 +645,9 @@ struct CYASSL_CTX {
|
|||||||
pem_password_cb passwd_cb;
|
pem_password_cb passwd_cb;
|
||||||
void* userdata;
|
void* userdata;
|
||||||
#endif /* OPENSSL_EXTRA */
|
#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 */
|
enum { /* ssl Constants */
|
||||||
SSL_ERROR_NONE = 0, /* for most functions */
|
SSL_ERROR_NONE = 0, /* for most functions */
|
||||||
SSL_FAILURE = 0, /* for some functions */
|
SSL_FAILURE = 0, /* for some functions */
|
||||||
SSL_SUCCESS = 1,
|
SSL_SUCCESS = 1,
|
||||||
|
|
||||||
SSL_BAD_CERTTYPE = -8,
|
SSL_BAD_CERTTYPE = -8,
|
||||||
SSL_BAD_STAT = -7,
|
SSL_BAD_STAT = -7,
|
||||||
@@ -794,6 +794,13 @@ CYASSL_API int CyaSSL_accept_ex(CYASSL*, HandShakeCallBack, TimeoutCallBack,
|
|||||||
#endif /* CYASSL_CALLBACKS */
|
#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
|
#ifdef __cplusplus
|
||||||
|
@@ -388,6 +388,9 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
|||||||
ctx->sendVerify = 0;
|
ctx->sendVerify = 0;
|
||||||
ctx->quietShutdown = 0;
|
ctx->quietShutdown = 0;
|
||||||
ctx->groupMessages = 0;
|
ctx->groupMessages = 0;
|
||||||
|
#ifdef HAVE_OCSP
|
||||||
|
CyaSSL_OCSP_Init(&ctx->ocsp);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (InitMutex(&ctx->countMutex) < 0) {
|
if (InitMutex(&ctx->countMutex) < 0) {
|
||||||
CYASSL_MSG("Mutex error on CTX init");
|
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);
|
XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
|
||||||
|
|
||||||
FreeSigners(ctx->caList, ctx->heap);
|
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
|
#ifdef OPENSSL_EXTRA
|
||||||
/* set X509 format for peer cert even if fatal */
|
/* set X509 format for peer cert even if fatal */
|
||||||
XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
|
XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
|
||||||
|
109
src/ocsp.c
109
src/ocsp.c
@@ -24,12 +24,117 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cyassl/error.h>
|
#include <cyassl/error.h>
|
||||||
#include <cyassl/ctaocrypt/asn.h>
|
#include <cyassl/ocsp.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_OCSP
|
#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 */
|
#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 */
|
#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