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; }
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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }