Beispiel #1
0
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
{
    int ret = OCSP_LOOKUP_FAIL;

#ifdef WOLFSSL_SMALL_STACK
    OcspRequest* ocspRequest;
#else
    OcspRequest ocspRequest[1];
#endif

    WOLFSSL_ENTER("CheckCertOCSP");


#ifdef WOLFSSL_SMALL_STACK
    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);
    if (ocspRequest == NULL) {
        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
        return MEMORY_E;
    }
#endif

    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce) == 0) {
        ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);

        FreeOcspRequest(ocspRequest);
    }

#ifdef WOLFSSL_SMALL_STACK
    XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif

    WOLFSSL_LEAVE("CheckCertOCSP", ret);
    return ret;
}
Beispiel #2
0
static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
                                                              OcspEntry** entry)
{
    WOLFSSL_ENTER("GetOcspEntry");

    *entry = NULL;

    if (LockMutex(&ocsp->ocspLock) != 0) {
        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
        return BAD_MUTEX_E;
    }

    for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
        if (XMEMCMP((*entry)->issuerHash,    request->issuerHash,
                                                         OCSP_DIGEST_SIZE) == 0
        &&  XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
                                                         OCSP_DIGEST_SIZE) == 0)
            break;

    if (*entry == NULL) {
        *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
                                                 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
        if (*entry) {
            InitOcspEntry(*entry, request);
            (*entry)->next = ocsp->ocspList;
            ocsp->ocspList = *entry;
        }
    }

    UnLockMutex(&ocsp->ocspLock);

    return *entry ? 0 : MEMORY_ERROR;
}
Beispiel #3
0
static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
{
    int ret = OCSP_INVALID_STATUS;

    WOLFSSL_ENTER("GetOcspStatus");

    *status = NULL;

    if (LockMutex(&ocsp->ocspLock) != 0) {
        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
        return BAD_MUTEX_E;
    }

    for (*status = entry->status; *status; *status = (*status)->next)
        if ((*status)->serialSz == request->serialSz
        &&  !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
            break;

    if (responseBuffer && *status && !(*status)->rawOcspResponse) {
        /* force fetching again */
        ret = OCSP_INVALID_STATUS;
    }
    else if (*status) {
        if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
        &&  ((*status)->nextDate[0] != 0)
        &&  ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
        {
            ret = xstat2err((*status)->status);

            if (responseBuffer) {
                responseBuffer->buffer = (byte*)XMALLOC(
                   (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);

                if (responseBuffer->buffer) {
                    responseBuffer->length = (*status)->rawOcspResponseSz;
                    XMEMCPY(responseBuffer->buffer,
                            (*status)->rawOcspResponse,
                            (*status)->rawOcspResponseSz);
                }
            }
        }
    }

    UnLockMutex(&ocsp->ocspLock);

    return ret;
}
Beispiel #4
0
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
{
    byte* ocspReqBuf = NULL;
    int ocspReqSz = 2048;
    byte* ocspRespBuf = NULL;
    int result = -1;
    OCSP_Entry* ocspe;
    CertStatus* certStatus = NULL;
    const char *url;
    int urlSz;
#ifdef WOLFSSL_SMALL_STACK
    CertStatus* newStatus;
    OcspRequest* ocspRequest;
    OcspResponse* ocspResponse;
#else
    CertStatus newStatus[1];
    OcspRequest ocspRequest[1];
    OcspResponse ocspResponse[1];
#endif

    WOLFSSL_ENTER("CheckCertOCSP");

    if (LockMutex(&ocsp->ocspLock) != 0) {
        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
        return BAD_MUTEX_E;
    }

    ocspe = ocsp->ocspList;
    while (ocspe) {
        if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
            && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
                                                        SHA_DIGEST_SIZE) == 0)
            break;
        else
            ocspe = ocspe->next;
    }

    if (ocspe == NULL) {
        ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
                                                NULL, DYNAMIC_TYPE_OCSP_ENTRY);
        if (ocspe != NULL) {
            InitOCSP_Entry(ocspe, cert);
            ocspe->next = ocsp->ocspList;
            ocsp->ocspList = ocspe;
        }
        else {
            UnLockMutex(&ocsp->ocspLock);
            WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
            return MEMORY_ERROR;
        }
    }
    else {
        certStatus = ocspe->status;
        while (certStatus) {
            if (certStatus->serialSz == cert->serialSz &&
                 XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
                break;
            else
                certStatus = certStatus->next;
        }
    }

    if (certStatus != NULL) {
        if (!ValidateDate(certStatus->thisDate,
                                        certStatus->thisDateFormat, BEFORE) ||
            (certStatus->nextDate[0] == 0) ||
            !ValidateDate(certStatus->nextDate,
                                        certStatus->nextDateFormat, AFTER)) {
            WOLFSSL_MSG("\tinvalid status date, looking up cert");
        }
        else {
            result = xstat2err(certStatus->status);
            UnLockMutex(&ocsp->ocspLock);
            WOLFSSL_LEAVE("CheckCertOCSP", result);
            return result;
        }
    }

    UnLockMutex(&ocsp->ocspLock);

    if (ocsp->cm->ocspUseOverrideURL) {
        url = ocsp->cm->ocspOverrideURL;
        if (url != NULL && url[0] != '\0')
            urlSz = (int)XSTRLEN(url);
        else
            return OCSP_NEED_URL;
    }
    else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
        url = (const char *)cert->extAuthInfo;
        urlSz = cert->extAuthInfoSz;
    }
    else {
        /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
        return 0;
    }

    ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
    if (ocspReqBuf == NULL) {
        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
        return MEMORY_ERROR;
    }

#ifdef WOLFSSL_SMALL_STACK
    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);
    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);
    ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);

    if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
        if (newStatus)    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
        if (ocspRequest)  XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
        if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);

        XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);

        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
        return MEMORY_E;
    }
#endif

    InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
                                                         ocspReqBuf, ocspReqSz);
    ocspReqSz = EncodeOcspRequest(ocspRequest);
    
    if (ocsp->cm->ocspIOCb)
        result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
                                           ocspReqBuf, ocspReqSz, &ocspRespBuf);

    if (result >= 0 && ocspRespBuf) {
        XMEMSET(newStatus, 0, sizeof(CertStatus));

        InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
        OcspResponseDecode(ocspResponse);
    
        if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
            result = OCSP_LOOKUP_FAIL;
        else {
            if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
                result = xstat2err(ocspResponse->status->status);

                if (LockMutex(&ocsp->ocspLock) != 0)
                    result = BAD_MUTEX_E;
                else {
                    if (certStatus != NULL)
                        /* Replace existing certificate entry with updated */
                        XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
                    else {
                        /* Save new certificate entry */
                        certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
                                          NULL, DYNAMIC_TYPE_OCSP_STATUS);
                        if (certStatus != NULL) {
                            XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
                            certStatus->next = ocspe->status;
                            ocspe->status = certStatus;
                            ocspe->totalStatus++;
                        }
                    }

                    UnLockMutex(&ocsp->ocspLock);
                }
            }
            else
                result = OCSP_LOOKUP_FAIL;
        }
    }
    else
        result = OCSP_LOOKUP_FAIL;

    XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);

#ifdef WOLFSSL_SMALL_STACK
    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
    XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif

    if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
        ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);

    WOLFSSL_LEAVE("CheckCertOCSP", result);
    return result;
}
Beispiel #5
0
int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
                                                      buffer* responseBuffer)
{
    OcspEntry*  entry          = NULL;
    CertStatus* status         = NULL;
    byte*       request        = NULL;
    int         requestSz      = 2048;
    byte*       response       = NULL;
    const char* url            = NULL;
    int         urlSz          = 0;
    int         ret            = -1;

#ifdef WOLFSSL_SMALL_STACK
    CertStatus* newStatus;
    OcspResponse* ocspResponse;
#else
    CertStatus newStatus[1];
    OcspResponse ocspResponse[1];
#endif

    WOLFSSL_ENTER("CheckOcspRequest");

    if (responseBuffer) {
        responseBuffer->buffer = NULL;
        responseBuffer->length = 0;
    }

    ret = GetOcspEntry(ocsp, ocspRequest, &entry);
    if (ret != 0)
        return ret;

    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
    if (ret != OCSP_INVALID_STATUS)
        return ret;

    if (ocsp->cm->ocspUseOverrideURL) {
        url = ocsp->cm->ocspOverrideURL;
        if (url != NULL && url[0] != '\0')
            urlSz = (int)XSTRLEN(url);
        else
            return OCSP_NEED_URL;
    }
    else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
        url = (const char *)ocspRequest->url;
        urlSz = ocspRequest->urlSz;
    }
    else {
        /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
        return 0;
    }

    request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_OCSP);
    if (request == NULL) {
        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
        return MEMORY_ERROR;
    }

#ifdef WOLFSSL_SMALL_STACK
    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);
    ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);

    if (newStatus == NULL || ocspResponse == NULL) {
        if (newStatus)    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
        if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);

        XFREE(request, NULL, DYNAMIC_TYPE_OCSP);

        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
        return MEMORY_E;
    }
#endif

    requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);

    if (ocsp->cm->ocspIOCb)
        ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
                                                 request, requestSz, &response);

    if (ret >= 0 && response) {
        XMEMSET(newStatus, 0, sizeof(CertStatus));

        InitOcspResponse(ocspResponse, newStatus, response, ret);
        OcspResponseDecode(ocspResponse, ocsp->cm);

        if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
            ret = OCSP_LOOKUP_FAIL;
        else {
            if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
                if (responseBuffer) {
                    responseBuffer->buffer = (byte*)XMALLOC(ret, NULL,
                                                       DYNAMIC_TYPE_TMP_BUFFER);

                    if (responseBuffer->buffer) {
                        responseBuffer->length = ret;
                        XMEMCPY(responseBuffer->buffer, response, ret);
                    }
                }

                ret = xstat2err(ocspResponse->status->status);

                if (LockMutex(&ocsp->ocspLock) != 0)
                    ret = BAD_MUTEX_E;
                else {
                    if (status != NULL) {
                        if (status->rawOcspResponse)
                            XFREE(status->rawOcspResponse, NULL,
                                                      DYNAMIC_TYPE_OCSP_STATUS);

                        /* Replace existing certificate entry with updated */
                        XMEMCPY(status, newStatus, sizeof(CertStatus));
                    }
                    else {
                        /* Save new certificate entry */
                        status = (CertStatus*)XMALLOC(sizeof(CertStatus),
                                          NULL, DYNAMIC_TYPE_OCSP_STATUS);
                        if (status != NULL) {
                            XMEMCPY(status, newStatus, sizeof(CertStatus));
                            status->next  = entry->status;
                            entry->status = status;
                            entry->totalStatus++;
                        }
                    }

                    if (status && responseBuffer && responseBuffer->buffer) {
                        status->rawOcspResponse = (byte*)XMALLOC(
                                                   responseBuffer->length, NULL,
                                                   DYNAMIC_TYPE_OCSP_STATUS);

                        if (status->rawOcspResponse) {
                            status->rawOcspResponseSz = responseBuffer->length;
                            XMEMCPY(status->rawOcspResponse,
                                    responseBuffer->buffer,
                                    responseBuffer->length);
                        }
                    }

                    UnLockMutex(&ocsp->ocspLock);
                }
            }
            else
                ret = OCSP_LOOKUP_FAIL;
        }
    }
    else
        ret = OCSP_LOOKUP_FAIL;

#ifdef WOLFSSL_SMALL_STACK
    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif

    if (response != NULL && ocsp->cm->ocspRespFreeCb)
        ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response);

    WOLFSSL_LEAVE("CheckOcspRequest", ret);
    return ret;
}
Beispiel #6
0
/* return 1 on success and 0 on failure.
 * By side effect returns private key, cert, and optionally ca.
 * Parses and decodes the parts of PKCS12
 *
 * NOTE: can parse with USER RSA enabled but may return cert that is not the
 *       pair for the key when using RSA key pairs.
 *
 * pkcs12 : non-null WC_PKCS12 struct
 * psw    : password to use for PKCS12 decode
 * pkey   : Private key returned
 * cert   : x509 cert returned
 * ca     : optional ca returned
 */
int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
        byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
        WC_DerCertList** ca)
{
    ContentInfo* ci       = NULL;
    WC_DerCertList* certList = NULL;
    byte* buf             = NULL;
    word32 i, oid;
    int ret, pswSz;

    WOLFSSL_ENTER("wc_PKCS12_parse");

    if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL ||
        pkey == NULL || pkeySz == NULL) {
        return BAD_FUNC_ARG;
    }
    pswSz = (int)XSTRLEN(psw);
    *cert = NULL;
    *pkey = NULL;
    if (ca != NULL) {
        *ca = NULL;
    }

    /* if there is sign data then verify the MAC */
    if (pkcs12->signData != NULL ) {
        if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data,
                               pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) {
            WOLFSSL_MSG("PKCS12 Bad MAC on verify");
            WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret);
            return MAC_CMP_FAILED_E;
        }
    }


    /* Decode content infos */
    ci = pkcs12->safe->CI;
    for (i = 0; i < pkcs12->safe->numCI; i++) {
        byte*  data;
        word32 idx = 0;
        int    size, totalSz;

        if (ci->type == WC_PKCS12_ENCRYPTED_DATA) {
            int number;

            WOLFSSL_MSG("Decrypting PKCS12 Content Info Container");
            data = ci->data;
            if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ASN_PARSE_E;
            }
            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

            if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

            if (number != 0) {
                WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12");
            }

            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

            ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz);
            if (ret < 0 || oid != WC_PKCS12_DATA) {
                WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error");
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ASN_PARSE_E;
            }

            /* decrypted content overwrites input buffer */
            size = ci->dataSz - idx;
            buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
            if (buf == NULL) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return MEMORY_E;
            }
            XMEMCPY(buf, data + idx, size);

            if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                WOLFSSL_MSG("Decryption failed, algorithm not compiled in?");
                return ret;
            }

            data = buf;
            idx = 0;
            #ifdef WOLFSSL_DEBUG_PKCS12
            {
                byte* p;
                for (printf("\tData = "), p = (byte*)buf;
                    p < (byte*)buf + size;
                    printf("%02X", *p), p++);
                printf("\n");
            }
            #endif
        }
        else { /* type DATA */
            WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container");
            data = ci->data;
            if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ASN_PARSE_E;
            }
            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }
            if (data[idx++] != ASN_OCTET_STRING) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ASN_PARSE_E;
            }
            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

        }

        /* parse through bags in ContentInfo */
        if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) {
            freeBuffers(*pkey, buf, pkcs12->heap);
            freeCertList(certList, pkcs12->heap);
            return ret;
        }
        totalSz += idx;

        while ((int)idx < totalSz) {
            int bagSz;
            if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }
            bagSz += idx;

            if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
                                                             ci->dataSz)) < 0) {
                freeBuffers(*pkey, buf, pkcs12->heap);
                freeCertList(certList, pkcs12->heap);
                return ret;
            }

            switch (oid) {
                case WC_PKCS12_KeyBag: /* 667 */
                    WOLFSSL_MSG("PKCS12 Key Bag found");
                    if (data[idx++] !=
                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ASN_PARSE_E;
                    }
                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ASN_PARSE_E;
                    }
                    if (*pkey == NULL) {
                        *pkey = (byte*)XMALLOC(size, pkcs12->heap,
                                                             DYNAMIC_TYPE_PKCS);
                        if (*pkey == NULL) {
                            freeBuffers(*pkey, buf, pkcs12->heap);
                            freeCertList(certList, pkcs12->heap);
                            return MEMORY_E;
                        }
                        XMEMCPY(*pkey, data + idx, size);
                        *pkeySz =  ToTraditional(*pkey, size);
                    }
                    #ifdef WOLFSSL_DEBUG_PKCS12
                        {
                            byte* p;
                            for (printf("\tKey = "), p = (byte*)*pkey;
                                p < (byte*)*pkey + size;
                                printf("%02X", *p), p++);
                            printf("\n");
                        }
                    #endif
                    idx += size;
                    break;

                case WC_PKCS12_ShroudedKeyBag: /* 668 */
                    {
                        byte* k;
                        WOLFSSL_MSG("PKCS12 Shrouded Key Bag found");
                        if (data[idx++] !=
                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                            freeBuffers(*pkey, buf, pkcs12->heap);
                            freeCertList(certList, pkcs12->heap);
                            return ASN_PARSE_E;
                        }
                        if ((ret = GetLength(data, &idx, &size,
                                                             ci->dataSz)) < 0) {
                            freeBuffers(*pkey, buf, pkcs12->heap);
                            freeCertList(certList, pkcs12->heap);
                            return ASN_PARSE_E;
                        }

                        k = (byte*)XMALLOC(size, pkcs12->heap,
                                                             DYNAMIC_TYPE_PKCS);
                        if (k == NULL) {
                            freeBuffers(*pkey, buf, pkcs12->heap);
                            freeCertList(certList, pkcs12->heap);
                            return MEMORY_E;
                        }
                        XMEMCPY(k, data + idx, size);

                        /* overwrites input, be warned */
                        if ((ret = ToTraditionalEnc(k, size, psw, pswSz)) < 0) {
                            freeBuffers(k, NULL, pkcs12->heap);
                            freeBuffers(*pkey, buf, pkcs12->heap);
                            freeCertList(certList, pkcs12->heap);
                            return ret;
                        }

                        if (ret < size) {
                            /* shrink key buffer */
                            k = (byte*)XREALLOC(k, ret, pkcs12->heap,
                                                             DYNAMIC_TYPE_PKCS);
                            if (k == NULL) {
                                freeBuffers(*pkey, buf, pkcs12->heap);
                                freeCertList(certList, pkcs12->heap);
                                return MEMORY_E;
                            }
                        }
                        size = ret;

                        if (*pkey == NULL) {
                            *pkey = k;
                            *pkeySz = size;
                        }
                        else { /* only expecting one key */
                            freeBuffers(k, NULL, pkcs12->heap);
                        }
                        idx += size;

                        #ifdef WOLFSSL_DEBUG_PKCS12
                        {
                            byte* p;
                            for (printf("\tKey = "), p = (byte*)k;
                                p < (byte*)k + ret;
                                printf("%02X", *p), p++);
                            printf("\n");
                        }
                        #endif
                    }
                    break;

                case WC_PKCS12_CertBag: /* 669 */
                {
                    WC_DerCertList* node;
                    WOLFSSL_MSG("PKCS12 Cert Bag found");
                    if (data[idx++] !=
                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ASN_PARSE_E;
                    }
                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ret;
                    }

                    /* get cert bag type */
                    if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ret;
                    }

                    if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
                                                             ci->dataSz)) < 0) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ret;
                    }

                    switch (oid) {
                        case WC_PKCS12_CertBag_Type1:  /* 675 */
                            /* type 1 */
                            WOLFSSL_MSG("PKCS12 cert bag type 1");
                            if (data[idx++] !=
                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
                                freeBuffers(*pkey, buf, pkcs12->heap);
                                freeCertList(certList, pkcs12->heap);
                                return ASN_PARSE_E;
                            }
                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
                                                                         <= 0) {
                                freeBuffers(*pkey, buf, pkcs12->heap);
                                freeCertList(certList, pkcs12->heap);
                                return ret;
                            }
                            if (data[idx++] != ASN_OCTET_STRING) {
                                freeBuffers(*pkey, buf, pkcs12->heap);
                                freeCertList(certList, pkcs12->heap);
                                return ASN_PARSE_E;
                            }
                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
                                                                          < 0) {
                                freeBuffers(*pkey, buf, pkcs12->heap);
                                freeCertList(certList, pkcs12->heap);
                                return ret;
                            }
                            break;
                       default:
                            WOLFSSL_MSG("Unknown PKCS12 cert bag type");
                    }

                    if (size + idx > (word32)bagSz) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return ASN_PARSE_E;
                    }

                    /* list to hold all certs found */
                    node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList),
                                               pkcs12->heap, DYNAMIC_TYPE_PKCS);
                    if (node == NULL) {
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return MEMORY_E;
                    }
                    XMEMSET(node, 0, sizeof(WC_DerCertList));

                    node->buffer = (byte*)XMALLOC(size, pkcs12->heap,
                                                             DYNAMIC_TYPE_PKCS);
                    if (node->buffer == NULL) {
                        XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS);
                        freeBuffers(*pkey, buf, pkcs12->heap);
                        freeCertList(certList, pkcs12->heap);
                        return MEMORY_E;
                    }
                    XMEMCPY(node->buffer, data + idx, size);
                    node->bufferSz = size;

                    /* put the new node into the list */
                    if (certList != NULL) {
                        WOLFSSL_MSG("Pushing new cert onto stack");
                        node->next = certList;
                        certList = node;
                    }
                    else {
                        certList = node;
                    }

                    /* on to next */
                    idx += size;
                }
                    break;

                case WC_PKCS12_CrlBag: /* 670 */
                    WOLFSSL_MSG("PKCS12 CRL BAG not yet supported");
                    break;

                case WC_PKCS12_SecretBag: /* 671 */
                    WOLFSSL_MSG("PKCS12 Secret BAG not yet supported");
                    break;

                case WC_PKCS12_SafeContentsBag: /* 672 */
                    WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported");
                    break;

                default:
                    WOLFSSL_MSG("Unknown PKCS12 BAG type found");
            }

            /* Attribute, unknown bag or unsupported */
            if ((int)idx < bagSz) {
                idx = bagSz; /* skip for now */
            }
        }

        /* free temporary buffer */
        if (buf != NULL) {
            XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
            buf = NULL;
        }
        ci = ci->next;
        WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container");
    }

    /* check if key pair, remove from list */
    {
        WC_DerCertList* current  = certList;
        WC_DerCertList* previous = NULL;

        if (*pkey != NULL) {

        while (current != NULL) {
            DecodedCert DeCert;
            InitDecodedCert(&DeCert, current->buffer, current->bufferSz,
                                                                  pkcs12->heap);
            if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) {
                if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) {
                    WOLFSSL_MSG("Key Pair found");
                    *cert = current->buffer;
                    *certSz = current->bufferSz;

                    if (previous == NULL) {
                        certList = current->next;
                    }
                    else {
                        previous->next = current->next;
                    }
                    FreeDecodedCert(&DeCert);
                    XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS);
                    break;
                }
            }

            FreeDecodedCert(&DeCert);
            previous = current;
            current  = current->next;
        }

        }
    }

    if (ca != NULL) {
        *ca = certList;
    }
    else {
        /* free list, not wanted */
        freeCertList(certList, pkcs12->heap);
    }

    return 1;
}
Beispiel #7
0
static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input,
                          word32* idx, int maxIdx)
{
    AuthenticatedSafe* safe;
    word32 oid;
    word32 localIdx = *idx;
    int ret;
    int size = 0;

    safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap,
                                       DYNAMIC_TYPE_PKCS);
    if (safe == NULL) {
        return MEMORY_E;
    }
    XMEMSET(safe, 0, sizeof(AuthenticatedSafe));

    ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx);
    if (ret < 0) {
        WOLFSSL_LEAVE("Get object id failed", ret);
        freeSafe(safe, pkcs12->heap);
        return ASN_PARSE_E;
    }

    safe->oid = oid;
    /* check tag, length */
    if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
        WOLFSSL_MSG("Unexpected tag in PKCS12 DER");
        freeSafe(safe, pkcs12->heap);
        return ASN_PARSE_E;
    }
    if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) {
        freeSafe(safe, pkcs12->heap);
        return ret;
    }

    switch (oid) {
        case WC_PKCS12_ENCRYPTED_DATA:
            WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n");
            break;

        case WC_PKCS12_DATA:
            WOLFSSL_MSG("Found PKCS12 OBJECT: DATA");
            /* get octets holding contents */
            if (input[localIdx++] != ASN_OCTET_STRING) {
                WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA");
                freeSafe(safe, pkcs12->heap);
                return ASN_PARSE_E;
            }
            if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) {
                freeSafe(safe, pkcs12->heap);
                return ret;
            }

            break;
    }

    safe->dataSz = size;
    safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
    if (safe->data == NULL) {
        freeSafe(safe, pkcs12->heap);
        return MEMORY_E;
    }
    XMEMCPY(safe->data, input + localIdx, size);
    *idx = localIdx;

    /* an instance of AuthenticatedSafe is created from
     * ContentInfo's strung together in a SEQUENCE. Here we itterate
     * through the ContentInfo's and add them to our
     * AuthenticatedSafe struct */
    localIdx = 0;
    input = safe->data;
    {
        int CISz;
        ret = GetSequence(input, &localIdx, &CISz, safe->dataSz);
        if (ret < 0) {
            freeSafe(safe, pkcs12->heap);
            return ASN_PARSE_E;
        }
        CISz += localIdx;
        while ((int)localIdx < CISz) {
            int curSz = 0;
            word32 curIdx;
            ContentInfo* ci = NULL;

            #ifdef WOLFSSL_DEBUG_PKCS12
                printf("\t\tlooking for Content Info.... ");
            #endif

            if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz))
                                                                          < 0) {
                freeSafe(safe, pkcs12->heap);
                return ret;
            }

            if (curSz > CISz) {
                /* subset should not be larger than universe */
                freeSafe(safe, pkcs12->heap);
                return ASN_PARSE_E;
            }

            curIdx = localIdx;
            if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType,
                                                           safe->dataSz)) < 0) {
                WOLFSSL_LEAVE("Get object id failed", ret);
                freeSafe(safe, pkcs12->heap);
                return ret;
            }

            /* create new content info struct ... possible OID sanity check? */
            ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap,
                                       DYNAMIC_TYPE_PKCS);
            if (ci == NULL) {
                freeSafe(safe, pkcs12->heap);
                return MEMORY_E;
            }

            ci->type   = oid;
            ci->dataSz = curSz - (localIdx-curIdx);
            ci->data   = (byte*)input + localIdx;
            localIdx  += ci->dataSz;

            #ifdef WOLFSSL_DEBUG_PKCS12
            switch (oid) {
                case WC_PKCS12_ENCRYPTED_DATA:
                    printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz);
                    break;

            case WC_PKCS12_DATA:
                    printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz);
                    break;
            default:
                    printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz);
            }
            #endif

            /* insert to head of list */
            ci->next = safe->CI;
            safe->CI = ci;
            safe->numCI += 1;
        }
    }

    pkcs12->safe = safe;
    *idx += localIdx;

    return 1;
}
Beispiel #8
0
int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
                                                             WOLFSSL_HEAP* heap)
{
    word32 ava = sz;
    byte*  pt  = buffer;
    int    ret = 0;
    word32 memSz = (word32)sizeof(wc_Memory);
    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);

    WOLFSSL_ENTER("wolfSSL_load_static_memory");

    if (buffer == NULL) {
        return BAD_FUNC_ARG;
    }

    /* align pt */
    while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
        *pt = 0x00;
        pt++;
        ava--;
    }

#ifdef WOLFSSL_DEBUG_MEMORY
    printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
#endif

    /* devide into chunks of memory and add them to available list */
    while (ava >= (heap->sizeList[0] + padSz + memSz)) {
        int i;
        /* creating only IO buffers from memory passed in, max TLS is 16k */
        if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
            if ((ret = create_memory_buckets(pt, ava,
                                          WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
                WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
                return ret;
            }

            /* check if no more room left for creating IO buffers */
            if (ret == 0) {
                break;
            }

            /* advance pointer in buffer for next buckets and keep track
               of how much memory is left available */
            pt  += ret;
            ava -= ret;
        }
        else {
            /* start at largest and move to smaller buckets */
            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
                if ((heap->sizeList[i] + padSz + memSz) <= ava) {
                    if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
                                     heap->distList[i], &(heap->ava[i]))) < 0) {
                        WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
                        return ret;
                    }

                    /* advance pointer in buffer for next buckets and keep track
                       of how much memory is left available */
                    pt  += ret;
                    ava -= ret;
                }
            }
        }
    }

    return 1;
}