Commit a4b83811 authored by Oleksii Beketov's avatar Oleksii Beketov Committed by Randeep

ParseChain update

1. ParseChain modified to get rid of 0x0 termination restriction.
Upon now the certificate chain may contain mix of PEM or DER
certificates with or without any separating symbols.
2. Add unit test for ParseChain

Change-Id: I6a2d6664c323e415e79fbddf63842b29fe15e338
Signed-off-by: default avatarOleksii Beketov <ol.beketov@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15509Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: default avatarGreg Zaverucha <gregz@microsoft.com>
Reviewed-by: default avatarJongsung Lee <js126.lee@samsung.com>
Reviewed-by: Randeep's avatarRandeep Singh <randeep.s@samsung.com>
Signed-off-by: default avatarOleksii Beketov <ol.beketov@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/16541Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
parent bff73296
......@@ -599,27 +599,23 @@ static int RecvCallBack(void * tep, unsigned char * data, size_t dataLen)
* Parse chain of X.509 certificates.
*
* @param[out] crt container for X.509 certificates
* @param[in] buf buffer with X.509 certificates. Certificates may be in either in PEM
or DER format in a jumble. Each PEM certificate must be NULL-terminated.
* @param[in] data buffer with X.509 certificates. Certificates may be in either in PEM
or DER format in a jumble, delimiting symbols does not matter.
* @param[in] bufLen buffer length
* @param[in] errNum number certificates that failed to parse
*
* @return 0 on success, -1 on error
* @return number of successfully parsed certificates or -1 on error
*/
static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, size_t bufLen)
static int ParseChain(mbedtls_x509_crt * crt, unsigned char * buf, int bufLen, int * errNum)
{
OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
VERIFY_NON_NULL_RET(crt, NET_SSL_TAG, "Param crt is NULL" , -1);
VERIFY_NON_NULL_RET(buf, NET_SSL_TAG, "Param buf is NULL" , -1);
size_t pos = 0;
size_t len = 0;
unsigned char * tmp = NULL;
/* byte encoded ASCII string '-----BEGIN CERTIFICATE-----' */
char pemCertHeader[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
};
// byte encoded ASCII string '-----END CERTIFICATE-----' */
char pemCertFooter[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
......@@ -627,6 +623,13 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, size_t
size_t pemCertHeaderLen = sizeof(pemCertHeader);
size_t pemCertFooterLen = sizeof(pemCertFooter);
size_t len = 0;
unsigned char * tmp = NULL;
int count = 0;
int ret = 0;
int pos = 0;
*errNum = 0;
while (pos < bufLen)
{
if (buf[pos] == 0x30 && buf[pos + 1] == 0x82)
......@@ -635,11 +638,21 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, size_t
CHECK_MBEDTLS_RET(mbedtls_asn1_get_len, &tmp, buf + bufLen, &len);
if (pos + len < bufLen)
{
CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse_der, crt, buf + pos, len + 4);
ret = mbedtls_x509_crt_parse_der(crt, buf + pos, len + 4);
if (0 == ret)
{
count++;
}
else
{
(*errNum)++;
OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse_der returned -0x%04x\n", -(ret));
}
}
pos += len + 4;
}
else if (0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen))
else if ((buf + pos + pemCertHeaderLen < buf + bufLen) &&
(0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen)))
{
void * endPos = NULL;
endPos = memmem(&(buf[pos]), bufLen - pos, pemCertFooter, pemCertFooterLen);
......@@ -649,36 +662,51 @@ static int ParseChain(mbedtls_x509_crt * crt, const unsigned char * buf, size_t
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0d) &&
(*((char*)endPos + pemCertFooterLen + 1) == 0x0a) &&
(*((char*)endPos + pemCertFooterLen + 2) == 0x00))
len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen;
if (pos + len + 1 <= bufLen)
{
len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 3;
}
else if ((*((char*)endPos + pemCertFooterLen + 0) == 0x0a) &&
(*((char*)endPos + pemCertFooterLen + 1) == 0x00))
{
len = (char*)endPos - ((char*)buf + pos) + pemCertFooterLen + 2;
char con = buf[pos + len];
buf[pos + len] = 0x00;
ret = mbedtls_x509_crt_parse(crt, buf + pos, len + 1);
if (0 == ret)
{
count++;
}
else
{
(*errNum)++;
OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
}
buf[pos + len] = con;
}
else
{
OIC_LOG_V(ERROR, NET_SSL_TAG, "Incorrect PEM certificate ending");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
unsigned char * lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
memcpy(lastCert, buf + pos, len);
lastCert[len] = 0x00;
ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
if (0 == ret)
{
count++;
}
else
{
(*errNum)++;
OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
}
OICFree(lastCert);
}
CHECK_MBEDTLS_RET(mbedtls_x509_crt_parse, crt, buf + pos, len);
pos += len;
}
else
{
OIC_LOG_BUFFER(DEBUG, NET_SSL_TAG, buf, bufLen);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
pos++;
}
}
OIC_LOG_V(DEBUG, NET_SSL_TAG, "%s successfully parsed %d certificates", __func__, count);
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return 0;
// exit label required for CHECK_MBEDTLS_RET macro
return count;
exit:
return -1;
}
......@@ -707,12 +735,19 @@ static int InitPKIX(CATransportAdapter_t adapter)
adapter == CA_ADAPTER_GATT_BTLE ?
&g_caSslContext->clientDtlsConf : &g_caSslContext->clientTlsConf);
// optional
int ret = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len);
if (0 != ret)
int ret;
int errNum;
int count = ParseChain(&g_caSslContext->crt, g_pkiInfo.crt.data, g_pkiInfo.crt.len, &errNum);
if (0 >= count)
{
OIC_LOG(WARNING, NET_SSL_TAG, "Own certificate chain parsing error");
goto required;
}
if (0 != errNum)
{
OIC_LOG_V(WARNING, NET_SSL_TAG, "Own certificate chain parsing error: %d certs failed to parse", errNum);
goto required;
}
ret = mbedtls_pk_parse_key(&g_caSslContext->pkey, g_pkiInfo.key.data, g_pkiInfo.key.len,
NULL, 0);
if (0 != ret)
......@@ -735,13 +770,17 @@ static int InitPKIX(CATransportAdapter_t adapter)
}
required:
ret = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len);
if(0 != ret)
count = ParseChain(&g_caSslContext->ca, g_pkiInfo.ca.data, g_pkiInfo.ca.len, &errNum);
if(0 >= count)
{
OIC_LOG(ERROR, NET_SSL_TAG, "CA chain parsing error");
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return -1;
}
if(0 != errNum)
{
OIC_LOG_V(WARNING, NET_SSL_TAG, "CA chain parsing warning: %d certs failed to parse", errNum);
}
ret = mbedtls_x509_crl_parse_der(&g_caSslContext->crl, g_pkiInfo.crl.data, g_pkiInfo.crl.len);
if(0 != ret)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment