forked from wolfSSL/wolfssl
adds support to nonce extension in OCSP stapling (status request tls extension);
fix nonce encoding, there was a missing ASN.1 OctetString header;
This commit is contained in:
@@ -984,8 +984,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||||
if (statusRequest) {
|
if (statusRequest) {
|
||||||
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP)
|
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP,
|
||||||
!= SSL_SUCCESS)
|
WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS)
|
||||||
err_sys("UseCertificateStatusRequest failed");
|
err_sys("UseCertificateStatusRequest failed");
|
||||||
|
|
||||||
wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
|
wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
|
||||||
|
12
src/ssl.c
12
src/ssl.c
@@ -796,21 +796,25 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
|
|||||||
|
|
||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||||
|
|
||||||
int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type)
|
int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type,
|
||||||
|
byte options)
|
||||||
{
|
{
|
||||||
if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
|
if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type);
|
return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
|
||||||
|
options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type)
|
int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type,
|
||||||
|
byte options)
|
||||||
{
|
{
|
||||||
if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
|
if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type);
|
return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
|
||||||
|
options);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
|
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
|
||||||
|
79
src/tls.c
79
src/tls.c
@@ -1909,6 +1909,8 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr)
|
|||||||
|
|
||||||
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
|
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
|
||||||
{
|
{
|
||||||
|
word16 size = 0;
|
||||||
|
|
||||||
/* shut up compiler warnings */
|
/* shut up compiler warnings */
|
||||||
(void) csr; (void) isRequest;
|
(void) csr; (void) isRequest;
|
||||||
|
|
||||||
@@ -1916,12 +1918,15 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
|
|||||||
if (isRequest) {
|
if (isRequest) {
|
||||||
switch (csr->status_type) {
|
switch (csr->status_type) {
|
||||||
case WOLFSSL_CSR_OCSP:
|
case WOLFSSL_CSR_OCSP:
|
||||||
return ENUM_LEN + 2 * OPAQUE16_LEN;
|
size += ENUM_LEN + 2 * OPAQUE16_LEN;
|
||||||
|
|
||||||
|
if (csr->request.ocsp.nonceSz)
|
||||||
|
size += MAX_OCSP_EXT_SZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
|
static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
|
||||||
@@ -1933,6 +1938,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
|
|||||||
#ifndef NO_WOLFSSL_CLIENT
|
#ifndef NO_WOLFSSL_CLIENT
|
||||||
if (isRequest) {
|
if (isRequest) {
|
||||||
word16 offset = 0;
|
word16 offset = 0;
|
||||||
|
word16 length = 0;
|
||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
output[offset++] = csr->status_type;
|
output[offset++] = csr->status_type;
|
||||||
@@ -1944,8 +1950,15 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
|
|||||||
offset += OPAQUE16_LEN;
|
offset += OPAQUE16_LEN;
|
||||||
|
|
||||||
/* request extensions */
|
/* request extensions */
|
||||||
c16toa(0, output + offset);
|
if (csr->request.ocsp.nonceSz)
|
||||||
offset += OPAQUE16_LEN;
|
length = EncodeOcspRequestExtensions(
|
||||||
|
&csr->request.ocsp,
|
||||||
|
output + offset + OPAQUE16_LEN,
|
||||||
|
MAX_OCSP_EXT_SZ);
|
||||||
|
|
||||||
|
c16toa(length, output + offset);
|
||||||
|
offset += OPAQUE16_LEN + length;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1980,9 +1993,25 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
|||||||
|
|
||||||
/* enable extension at ssl level */
|
/* enable extension at ssl level */
|
||||||
ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
||||||
csr->status_type);
|
csr->status_type, csr->options);
|
||||||
if (ret != SSL_SUCCESS)
|
if (ret != SSL_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
switch (csr->status_type) {
|
||||||
|
case WOLFSSL_CSR_OCSP:
|
||||||
|
/* propagate nonce */
|
||||||
|
if (csr->request.ocsp.nonceSz) {
|
||||||
|
OcspRequest* request =
|
||||||
|
TLSX_CSR_GetRequest(ssl->extensions);
|
||||||
|
|
||||||
|
if (request) {
|
||||||
|
XMEMCPY(request->nonce, csr->request.ocsp.nonce,
|
||||||
|
csr->request.ocsp.nonceSz);
|
||||||
|
request->nonceSz = csr->request.ocsp.nonceSz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl->status_request = 1;
|
ssl->status_request = 1;
|
||||||
@@ -1998,15 +2027,29 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert)
|
|||||||
{
|
{
|
||||||
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
|
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
|
||||||
CertificateStatusRequest* csr = extension ? extension->data : NULL;
|
CertificateStatusRequest* csr = extension ? extension->data : NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (csr) {
|
if (csr) {
|
||||||
switch (csr->status_type) {
|
switch (csr->status_type) {
|
||||||
case WOLFSSL_CSR_OCSP:
|
case WOLFSSL_CSR_OCSP: {
|
||||||
return InitOcspRequest(&csr->request.ocsp, cert, 0);
|
byte nonce[MAX_OCSP_NONCE_SZ];
|
||||||
|
int nonceSz = csr->request.ocsp.nonceSz;
|
||||||
|
|
||||||
|
/* preserve nonce */
|
||||||
|
XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz);
|
||||||
|
|
||||||
|
if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0)) != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* restore nonce */
|
||||||
|
XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz);
|
||||||
|
csr->request.ocsp.nonceSz = nonceSz;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* TLSX_CSR_GetRequest(TLSX* extensions)
|
void* TLSX_CSR_GetRequest(TLSX* extensions)
|
||||||
@@ -2044,7 +2087,8 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
|
int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
|
||||||
|
byte options)
|
||||||
{
|
{
|
||||||
CertificateStatusRequest* csr = NULL;
|
CertificateStatusRequest* csr = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -2060,6 +2104,23 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
|
|||||||
ForceZero(csr, sizeof(CertificateStatusRequest));
|
ForceZero(csr, sizeof(CertificateStatusRequest));
|
||||||
|
|
||||||
csr->status_type = status_type;
|
csr->status_type = status_type;
|
||||||
|
csr->options = options;
|
||||||
|
|
||||||
|
switch (csr->status_type) {
|
||||||
|
case WOLFSSL_CSR_OCSP:
|
||||||
|
if (options & WOLFSSL_CSR_OCSP_USE_NONCE) {
|
||||||
|
WC_RNG rng;
|
||||||
|
|
||||||
|
if (wc_InitRng(&rng) == 0) {
|
||||||
|
if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce,
|
||||||
|
MAX_OCSP_NONCE_SZ) == 0)
|
||||||
|
csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
|
||||||
|
|
||||||
|
wc_FreeRng(&rng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) {
|
if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) {
|
||||||
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);
|
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);
|
||||||
|
@@ -8786,53 +8786,40 @@ int OcspResponseDecode(OcspResponse* resp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static word32 SetOcspReqExtensions(word32 extSz, byte* output,
|
word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
|
||||||
const byte* nonce, word32 nonceSz)
|
|
||||||
{
|
{
|
||||||
static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
|
static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
|
||||||
0x30, 0x01, 0x02 };
|
0x30, 0x01, 0x02 };
|
||||||
byte seqArray[5][MAX_SEQ_SZ];
|
byte seqArray[6][MAX_SEQ_SZ];
|
||||||
word32 seqSz[5], totalSz;
|
word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId);
|
||||||
|
|
||||||
WOLFSSL_ENTER("SetOcspReqExtensions");
|
WOLFSSL_ENTER("SetOcspReqExtensions");
|
||||||
|
|
||||||
if (nonce == NULL || nonceSz == 0) return 0;
|
if (!req || !output || !req->nonceSz)
|
||||||
|
return 0;
|
||||||
|
|
||||||
seqArray[0][0] = ASN_OCTET_STRING;
|
totalSz += req->nonceSz;
|
||||||
seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
|
totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]);
|
||||||
|
totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]);
|
||||||
|
seqArray[2][0] = ASN_OBJECT_ID;
|
||||||
|
totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]);
|
||||||
|
totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]);
|
||||||
|
totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]);
|
||||||
|
totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]);
|
||||||
|
|
||||||
seqArray[1][0] = ASN_OBJECT_ID;
|
if (totalSz < size)
|
||||||
seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]);
|
|
||||||
|
|
||||||
totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId);
|
|
||||||
|
|
||||||
seqSz[2] = SetSequence(totalSz, seqArray[2]);
|
|
||||||
totalSz += seqSz[2];
|
|
||||||
|
|
||||||
seqSz[3] = SetSequence(totalSz, seqArray[3]);
|
|
||||||
totalSz += seqSz[3];
|
|
||||||
|
|
||||||
seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2);
|
|
||||||
seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]);
|
|
||||||
totalSz += seqSz[4];
|
|
||||||
|
|
||||||
if (totalSz < extSz)
|
|
||||||
{
|
{
|
||||||
totalSz = 0;
|
totalSz = 0;
|
||||||
XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
|
XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); totalSz += seqSz[5];
|
||||||
totalSz += seqSz[4];
|
XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4];
|
||||||
XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
|
XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); totalSz += seqSz[3];
|
||||||
totalSz += seqSz[3];
|
XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); totalSz += seqSz[2];
|
||||||
XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
|
|
||||||
totalSz += seqSz[2];
|
|
||||||
XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
|
|
||||||
totalSz += seqSz[1];
|
|
||||||
XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
|
XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
|
||||||
totalSz += (word32)sizeof(NonceObjId);
|
totalSz += (word32)sizeof(NonceObjId);
|
||||||
XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
|
XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); totalSz += seqSz[1];
|
||||||
totalSz += seqSz[0];
|
XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); totalSz += seqSz[0];
|
||||||
XMEMCPY(output + totalSz, nonce, nonceSz);
|
XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
|
||||||
totalSz += nonceSz;
|
totalSz += req->nonceSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalSz;
|
return totalSz;
|
||||||
@@ -8865,8 +8852,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
|
|||||||
extSz = 0;
|
extSz = 0;
|
||||||
|
|
||||||
if (req->nonceSz)
|
if (req->nonceSz)
|
||||||
extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
|
extSz = EncodeOcspRequestExtensions(req, extArray, MAX_OCSP_EXT_SZ);
|
||||||
req->nonce, req->nonceSz);
|
|
||||||
|
|
||||||
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
|
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
|
||||||
for (i = 4; i >= 0; i--) {
|
for (i = 4; i >= 0; i--) {
|
||||||
|
@@ -1576,13 +1576,14 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte status_type;
|
byte status_type;
|
||||||
|
byte options;
|
||||||
union {
|
union {
|
||||||
OcspRequest ocsp;
|
OcspRequest ocsp;
|
||||||
} request;
|
} request;
|
||||||
} CertificateStatusRequest;
|
} CertificateStatusRequest;
|
||||||
|
|
||||||
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
|
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions,
|
||||||
byte status_type);
|
byte status_type, byte options);
|
||||||
WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert);
|
WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert);
|
||||||
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
|
WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
|
||||||
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
|
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
|
||||||
|
@@ -1413,14 +1413,19 @@ enum {
|
|||||||
WOLFSSL_CSR_OCSP = 1
|
WOLFSSL_CSR_OCSP = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Certificate Status Options (flags) */
|
||||||
|
enum {
|
||||||
|
WOLFSSL_CSR_OCSP_USE_NONCE = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||||
#ifndef NO_WOLFSSL_CLIENT
|
#ifndef NO_WOLFSSL_CLIENT
|
||||||
|
|
||||||
WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl,
|
WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl,
|
||||||
unsigned char status_type);
|
unsigned char status_type, unsigned char options);
|
||||||
|
|
||||||
WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx,
|
WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx,
|
||||||
unsigned char status_type);
|
unsigned char status_type, unsigned char options);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@@ -188,7 +188,7 @@ enum Misc_ASN {
|
|||||||
MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ,
|
MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ,
|
||||||
#endif
|
#endif
|
||||||
MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */
|
MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */
|
||||||
MAX_OCSP_NONCE_SZ = 18, /* OCSP Nonce size */
|
MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */
|
||||||
EIGHTK_BUF = 8192, /* Tmp buffer size */
|
EIGHTK_BUF = 8192, /* Tmp buffer size */
|
||||||
MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
|
MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
|
||||||
/* use bigger NTRU size */
|
/* use bigger NTRU size */
|
||||||
@@ -725,6 +725,8 @@ WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*);
|
|||||||
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
|
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
|
||||||
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
|
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
|
||||||
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
|
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
|
||||||
|
WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32);
|
||||||
|
|
||||||
|
|
||||||
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*);
|
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user