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:
Moisés Guimarães
2015-10-26 18:09:09 -03:00
parent 14fa980dad
commit a47f98ee19
7 changed files with 118 additions and 59 deletions

View File

@@ -984,8 +984,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (statusRequest) {
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP)
!= SSL_SUCCESS)
if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP,
WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS)
err_sys("UseCertificateStatusRequest failed");
wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);

View File

@@ -796,21 +796,25 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
#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)
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)
return BAD_FUNC_ARG;
return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type);
return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
options);
}
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */

View File

@@ -1909,6 +1909,8 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr)
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
{
word16 size = 0;
/* shut up compiler warnings */
(void) csr; (void) isRequest;
@@ -1916,12 +1918,15 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
if (isRequest) {
switch (csr->status_type) {
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
return 0;
return size;
}
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
if (isRequest) {
word16 offset = 0;
word16 length = 0;
/* type */
output[offset++] = csr->status_type;
@@ -1944,8 +1950,15 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
offset += OPAQUE16_LEN;
/* request extensions */
c16toa(0, output + offset);
offset += OPAQUE16_LEN;
if (csr->request.ocsp.nonceSz)
length = EncodeOcspRequestExtensions(
&csr->request.ocsp,
output + offset + OPAQUE16_LEN,
MAX_OCSP_EXT_SZ);
c16toa(length, output + offset);
offset += OPAQUE16_LEN + length;
break;
}
@@ -1980,9 +1993,25 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
/* enable extension at ssl level */
ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
csr->status_type);
csr->status_type, csr->options);
if (ret != SSL_SUCCESS)
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;
@@ -1998,15 +2027,29 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert)
{
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
CertificateStatusRequest* csr = extension ? extension->data : NULL;
int ret = 0;
if (csr) {
switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
return InitOcspRequest(&csr->request.ocsp, cert, 0);
case WOLFSSL_CSR_OCSP: {
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)
@@ -2044,7 +2087,8 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
return 0;
}
int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
byte options)
{
CertificateStatusRequest* csr = NULL;
int ret = 0;
@@ -2060,6 +2104,23 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type)
ForceZero(csr, sizeof(CertificateStatusRequest));
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) {
XFREE(csr, NULL, DYNAMIC_TYPE_TLSX);

View File

@@ -8786,53 +8786,40 @@ int OcspResponseDecode(OcspResponse* resp)
}
static word32 SetOcspReqExtensions(word32 extSz, byte* output,
const byte* nonce, word32 nonceSz)
word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
{
static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
0x30, 0x01, 0x02 };
byte seqArray[5][MAX_SEQ_SZ];
word32 seqSz[5], totalSz;
byte seqArray[6][MAX_SEQ_SZ];
word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId);
WOLFSSL_ENTER("SetOcspReqExtensions");
if (nonce == NULL || nonceSz == 0) return 0;
if (!req || !output || !req->nonceSz)
return 0;
seqArray[0][0] = ASN_OCTET_STRING;
seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
totalSz += req->nonceSz;
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;
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)
if (totalSz < size)
{
totalSz = 0;
XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
totalSz += seqSz[4];
XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
totalSz += seqSz[3];
XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
totalSz += seqSz[2];
XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
totalSz += seqSz[1];
XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); totalSz += seqSz[5];
XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4];
XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); totalSz += seqSz[3];
XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); totalSz += seqSz[2];
XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
totalSz += (word32)sizeof(NonceObjId);
XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
totalSz += seqSz[0];
XMEMCPY(output + totalSz, nonce, nonceSz);
totalSz += nonceSz;
XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); totalSz += seqSz[1];
XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); totalSz += seqSz[0];
XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
totalSz += req->nonceSz;
}
return totalSz;
@@ -8865,8 +8852,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
extSz = 0;
if (req->nonceSz)
extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
req->nonce, req->nonceSz);
extSz = EncodeOcspRequestExtensions(req, extArray, MAX_OCSP_EXT_SZ);
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
for (i = 4; i >= 0; i--) {

View File

@@ -1576,13 +1576,14 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
typedef struct {
byte status_type;
byte options;
union {
OcspRequest ocsp;
} request;
} CertificateStatusRequest;
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 void* TLSX_CSR_GetRequest(TLSX* extensions);
WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);

View File

@@ -1413,14 +1413,19 @@ enum {
WOLFSSL_CSR_OCSP = 1
};
/* Certificate Status Options (flags) */
enum {
WOLFSSL_CSR_OCSP_USE_NONCE = 0x01
};
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
#ifndef NO_WOLFSSL_CLIENT
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,
unsigned char status_type);
unsigned char status_type, unsigned char options);
#endif
#endif

View File

@@ -188,7 +188,7 @@ enum Misc_ASN {
MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ,
#endif
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 */
MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
/* use bigger NTRU size */
@@ -722,9 +722,11 @@ struct OcspRequest {
WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*);
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte);
WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);
WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32);
WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32);
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*);