int KSI_PKISignature_serialize(KSI_PKISignature *sig, unsigned char **raw, unsigned *raw_len) { int res = KSI_UNKNOWN_ERROR; unsigned char *tmp = NULL; if (sig == NULL || raw == NULL || raw_len == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(sig->ctx); tmp = KSI_malloc(sig->pkcs7.cbData); if (tmp == NULL) { KSI_pushError(sig->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmp, sig->pkcs7.pbData, sig->pkcs7.cbData); *raw = tmp; *raw_len = (unsigned)sig->pkcs7.cbData; tmp = NULL; res = KSI_OK; cleanup: KSI_free(tmp); return res; }
int KSI_PKICertificate_serialize(KSI_PKICertificate *cert, unsigned char **raw, size_t *raw_len) { int res = KSI_UNKNOWN_ERROR; unsigned char *tmp_serialized = NULL; DWORD len = 0; if (cert == NULL || raw == NULL || raw_len == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(cert->ctx); len = cert->x509->cbCertEncoded; tmp_serialized = KSI_malloc(len); if (tmp_serialized == NULL) { KSI_pushError(cert->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmp_serialized, cert->x509->pbCertEncoded, len); *raw = tmp_serialized; *raw_len = (size_t)len; tmp_serialized = NULL; res = KSI_OK; cleanup: KSI_free(tmp_serialized); return res; }
int KSI_Utf8String_new(KSI_CTX *ctx, const char *str, size_t len, KSI_Utf8String **o) { int res = KSI_UNKNOWN_ERROR; KSI_Utf8String *tmp = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || str == NULL || o == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } tmp = KSI_new(KSI_Utf8String); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp->ctx = ctx; tmp->value = NULL; tmp->ref = 1; /* Verify that it is a null-terminated string. */ if (len == 0 || str[len - 1] != '\0') { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "String value is not null-terminated."); goto cleanup; } /* Verify correctness of utf-8 */ res = verifyUtf8((const unsigned char *)str, len); if (res != KSI_OK) goto cleanup; tmp->value = KSI_malloc(len); if (tmp->value == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmp->value, str, len); tmp->len = len; *o = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_Utf8String_free(tmp); return res; }
int KSI_PKISignature_new(KSI_CTX *ctx, const void *raw, unsigned raw_len, KSI_PKISignature **signature) { int res = KSI_UNKNOWN_ERROR; KSI_PKISignature *tmp = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || raw == NULL || raw_len == 0 || signature == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } tmp = KSI_new(KSI_PKISignature); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp->ctx = ctx; tmp->pkcs7.pbData = NULL; tmp->pkcs7.cbData = 0; if (raw_len > UINT_MAX) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Length is more than MAX_INT."); goto cleanup; } tmp->pkcs7.pbData = KSI_malloc(raw_len); if (tmp->pkcs7.pbData == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp->pkcs7.cbData = raw_len; memcpy(tmp->pkcs7.pbData, raw, raw_len); *signature = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_PKISignature_free(tmp); return res; }
int KSI_PKICertificate_serialize(KSI_PKICertificate *cert, unsigned char **raw, unsigned *raw_len) { int res = KSI_UNKNOWN_ERROR; unsigned char *tmp_serialized = NULL; DWORD len = 0; char buf[1024]; if (cert == NULL || raw == NULL || raw_len == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(cert->ctx); if (!CertSerializeCertificateStoreElement(cert->x509, 0, NULL, &len)) { KSI_LOG_debug(cert->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(cert->ctx, res = KSI_CRYPTO_FAILURE, "Unable to serialize PKI certificate."); goto cleanup; } tmp_serialized = KSI_malloc(len); if (tmp_serialized == NULL) { KSI_pushError(cert->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } if (!CertSerializeCertificateStoreElement(cert->x509, 0, (BYTE*)tmp_serialized, &len)){ KSI_LOG_debug(cert->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(cert->ctx, res = KSI_CRYPTO_FAILURE, "Unable to serialize PKI certificate."); goto cleanup; } *raw = tmp_serialized; *raw_len = (unsigned)len; tmp_serialized = NULL; res = KSI_OK; cleanup: KSI_free(tmp_serialized); return res; }
int KSI_OctetString_new(KSI_CTX *ctx, const unsigned char *data, size_t data_len, KSI_OctetString **o) { int res = KSI_UNKNOWN_ERROR; KSI_OctetString *tmp = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || (data == NULL && data_len != 0) || o == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } tmp = KSI_new(KSI_OctetString); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp->ctx = ctx; tmp->data = NULL; tmp->data_len = data_len; tmp->ref = 1; if (data_len > 0) { tmp->data = KSI_malloc(data_len); if (tmp->data == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmp->data, data, data_len); } *o = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_OctetString_free(tmp); return res; }
static int generateNextTlv(struct generator_st *gen, KSI_TLV **tlv) { int res = KSI_UNKNOWN_ERROR; unsigned char *buf = NULL; size_t consumed = 0; KSI_FTLV ftlv; if (gen == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } if (gen->tlv != NULL) { KSI_TLV_free(gen->tlv); gen->tlv = NULL; } /* Try to parse only when there is something left to parse. */ if (gen->len > 0) { memset(&ftlv, 0, sizeof(ftlv)); res = KSI_FTLV_memRead(gen->ptr, gen->len, &ftlv); if (res != KSI_OK) { KSI_pushError(gen->ctx, res, NULL); goto cleanup; } consumed = ftlv.hdr_len + ftlv.dat_len; buf = KSI_malloc(consumed); if (buf == NULL) { KSI_pushError(gen->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(buf, gen->ptr, consumed); gen->ptr += consumed; gen->len -= consumed; /* Make sure the buffer is not overflowing. */ if (consumed > UINT_MAX){ KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "Input too large."); goto cleanup; } if (consumed > 0) { if (gen->hasSignature) { /* The signature must be the last element. */ KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "The signature must be the last element."); goto cleanup; } res = KSI_TLV_parseBlob2(gen->ctx, buf, (unsigned)consumed, 1, &gen->tlv); if (res != KSI_OK) { KSI_pushError(gen->ctx, res, NULL); goto cleanup; } buf = NULL; if (KSI_TLV_getTag(gen->tlv) == 0x0704) { gen->sig_offset = gen->offset; gen->hasSignature = true; } } } gen->offset += consumed; *tlv = gen->tlv; res = KSI_OK; cleanup: KSI_free(buf); return res; }
int KSI_PublicationsFile_serialize(KSI_CTX *ctx, KSI_PublicationsFile *pubFile, char **raw, size_t *raw_len) { int res; const unsigned char *buf = NULL; size_t buf_len = 0; KSI_TLV *tlv = NULL; unsigned char *tmp = NULL; size_t tmp_len = 0; size_t sig_len = 0; KSI_ERR_clearErrors(ctx); if (ctx == NULL || pubFile == 0 || raw == NULL || raw_len == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } /** * Create TLV 0x700 that contains nested list of publication file TLVs. * Calculate signed data length assuming that signature TLV is always the last. */ res = KSI_TLV_new(ctx, 0x700, 0, 0, &tlv); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_TlvTemplate_construct(ctx, tlv, pubFile, KSI_TLV_TEMPLATE(KSI_PublicationsFile)); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = publicationsFileTLV_getSignatureTLVLength(tlv, &sig_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_TLV_getRawValue(tlv, &buf, &buf_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } /** * Append raw value to publication file header. Copy raw publication file into * internal and external buffer. */ tmp_len = buf_len + sizeof(PUB_FILE_HEADER_ID) - 1; tmp = (unsigned char *) KSI_malloc(tmp_len); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } if (KSI_strncpy((char *)tmp, PUB_FILE_HEADER_ID, tmp_len) == NULL) { KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, NULL); goto cleanup; } memcpy(tmp + sizeof(PUB_FILE_HEADER_ID) - 1, buf, buf_len); if (pubFile->raw != NULL) KSI_free(pubFile->raw); pubFile->raw = tmp; pubFile->raw_len = tmp_len; pubFile->signedDataLength = tmp_len - sig_len; tmp = NULL; tmp = (unsigned char *) KSI_malloc(pubFile->raw_len); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmp, pubFile->raw, pubFile->raw_len); *raw = (char *)tmp; *raw_len = pubFile->raw_len; tmp = NULL; res = KSI_OK; cleanup: KSI_TLV_free(tlv); KSI_free(tmp); return res; }
int KSI_PublicationsFile_parse(KSI_CTX *ctx, const void *raw, size_t raw_len, KSI_PublicationsFile **pubFile) { int res; KSI_PublicationsFile *tmp = NULL; struct generator_st gen = {ctx, raw, raw_len, NULL, 0, 0, false}; unsigned char *tmpRaw = NULL; const size_t hdrLen = strlen(PUB_FILE_HEADER_ID); KSI_ERR_clearErrors(ctx); if (ctx == NULL || raw == NULL || raw_len == 0 || pubFile == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } /* Check the header. */ if (gen.len < hdrLen || memcmp(gen.ptr, PUB_FILE_HEADER_ID, hdrLen)) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unrecognized header."); goto cleanup; } /* Header verification ok - create the store object. */ res = KSI_PublicationsFile_new(ctx, &tmp); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } tmp->signedDataLength = hdrLen; /* Initialize generator. */ gen.ptr += hdrLen; gen.len -= hdrLen; /* Read the payload of the file, and make no assumptions with the ordering. */ res = KSI_TlvTemplate_extractGenerator(ctx, tmp, (void *)&gen, KSI_TLV_TEMPLATE(KSI_PublicationsFile), (int (*)(void *, KSI_TLV **))generateNextTlv); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } tmp->signedDataLength += gen.sig_offset; /* Copy the raw value */ tmpRaw = KSI_malloc(raw_len); if (tmpRaw == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(tmpRaw, raw, raw_len); tmp->raw = tmpRaw; tmp->raw_len = raw_len; tmpRaw = NULL; *pubFile = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_free(tmpRaw); KSI_TLV_free(gen.tlv); KSI_PublicationsFile_free(tmp); return res; }
/*cert obj must be freed*/ static int extractSigningCertificate(const KSI_PKISignature *signature, PCCERT_CONTEXT *cert) { int res = KSI_UNKNOWN_ERROR; KSI_CTX *ctx = NULL; HCERTSTORE certStore = NULL; DWORD signerCount = 0; PCERT_INFO pSignerCertInfo = NULL; HCRYPTMSG signaturMSG = NULL; PCCERT_CONTEXT signing_cert = NULL; BYTE *dataRecieved = NULL; char buf[1024]; DWORD dataLen = 0; if (signature == NULL || cert == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } ctx = signature->ctx; KSI_ERR_clearErrors(ctx); /*Get Signature certificates as a certificate store*/ certStore = CryptGetMessageCertificates(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, (HCRYPTPROV_LEGACY)NULL, 0, signature->pkcs7.pbData, signature->pkcs7.cbData); if (certStore == NULL){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get signatures PKI certificates."); goto cleanup; } /*Counting signing certificates*/ signerCount = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, signature->pkcs7.pbData, signature->pkcs7.cbData); if (signerCount == -1){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to count PKI signatures certificates."); goto cleanup; } /*Is there exactly 1 signing cert?*/ if (signerCount != 1){ KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "PKI signature certificate count is not 1."); goto cleanup; } /*Open signature for decoding*/ signaturMSG = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0,0, NULL, NULL); if (signaturMSG == NULL){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == E_INVALIDARG) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg); else if (error == E_OUTOFMEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); else KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg); goto cleanup; } if (!CryptMsgUpdate(signaturMSG, signature->pkcs7.pbData, signature->pkcs7.cbData, TRUE)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == E_OUTOFMEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); else if (error == CRYPT_E_UNEXPECTED_ENCODING) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature is not encoded as PKCS7."); else if (error == CRYPT_E_MSG_ERROR) KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, errmsg); else KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg); goto cleanup; } /*Get signatures signing cert id*/ if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, NULL, &dataLen)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == CRYPT_E_ATTRIBUTES_MISSING) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature does not contain signing certificate id."); else KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg); goto cleanup; } dataRecieved = KSI_malloc(dataLen); if (dataRecieved == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, dataRecieved, &dataLen)){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get PKI signatures signing certificate id."); goto cleanup; } pSignerCertInfo = (PCERT_INFO)dataRecieved; /*Get signing cert*/ signing_cert = CertGetSubjectCertificateFromStore(certStore, X509_ASN_ENCODING, pSignerCertInfo); if (signing_cert == NULL){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get PKI signatures signer certificate."); goto cleanup; } /*The copy of the object is NOT created. Just its reference value is incremented*/ signing_cert = CertDuplicateCertificateContext(signing_cert); *cert = signing_cert; signing_cert = NULL; res = KSI_OK; cleanup: if (signing_cert) CertFreeCertificateContext(signing_cert); if (certStore) CertCloseStore(certStore, CERT_CLOSE_STORE_CHECK_FLAG); if (signaturMSG) CryptMsgClose(signaturMSG); KSI_free(dataRecieved); return res; }
int KSI_PKITruststore_verifyRawSignature(KSI_CTX *ctx, const unsigned char *data, unsigned data_len, const char *algoOid, const unsigned char *signature, unsigned signature_len, const KSI_PKICertificate *certificate) { int res = KSI_UNKNOWN_ERROR; ALG_ID algorithm=0; HCRYPTPROV hCryptProv = 0; PCCERT_CONTEXT subjectCert = NULL; HCRYPTKEY publicKey = 0; DWORD i=0; BYTE *little_endian_pkcs1= NULL; DWORD pkcs1_len = 0; HCRYPTHASH hash = 0; char buf[1024]; KSI_ERR_clearErrors(ctx); if (ctx == NULL || data == NULL || signature == NULL || signature_len >= UINT_MAX || algoOid == NULL || certificate == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } algorithm = algIdFromOID(algoOid); if (algorithm == 0) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL); goto cleanup; } // Get the CSP context if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get cryptographic provider."); goto cleanup; } // Get the public key from the issuer certificate subjectCert = certificate->x509; if (!CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,&subjectCert->pCertInfo->SubjectPublicKeyInfo,&publicKey)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Failed to read PKI public key."); goto cleanup; } /*Convert big-endian to little-endian PKCS#1 signature*/ pkcs1_len = signature_len; little_endian_pkcs1 = (BYTE*)KSI_malloc(pkcs1_len); if (little_endian_pkcs1 == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } for (i=0; i<pkcs1_len; i++){ little_endian_pkcs1[pkcs1_len-1-i] = signature[i]; } // Create the hash object and hash input data. if (!CryptCreateHash(hCryptProv, algorithm, 0, 0, &hash)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to create hasher."); goto cleanup; } if (!CryptHashData(hash, (BYTE*)data, data_len,0)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to hash data."); goto cleanup; } /*Verify the signature. The format MUST be PKCS#1*/ if (!CryptVerifySignature(hash, (BYTE*)little_endian_pkcs1, pkcs1_len, publicKey, NULL, 0)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(ctx, "%s", errmsg); if (error == NTE_BAD_SIGNATURE) KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Invalid PKI signature."); else if (error == NTE_NO_MEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, "Unable to verify PKI signature. CSP out of memory."); else KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, errmsg); goto cleanup; } KSI_LOG_debug(certificate->ctx, "CryptoAPI: PKI signature verified successfully."); res = KSI_OK; cleanup: KSI_free(little_endian_pkcs1); if (hCryptProv) CryptReleaseContext(hCryptProv, 0); if (hash) CryptDestroyHash(hash); return res; }
int KSI_CTX_new(KSI_CTX **context) { int res = KSI_UNKNOWN_ERROR; KSI_CTX *ctx = NULL; KSI_NetworkClient *client = NULL; ctx = KSI_new(KSI_CTX); if (ctx == NULL) { res = KSI_OUT_OF_MEMORY; goto cleanup; } /* Init error stack */ ctx->errors_size = KSI_ERR_STACK_LEN; ctx->errors = KSI_malloc(sizeof(KSI_ERR) * ctx->errors_size); if (ctx->errors == NULL) { res = KSI_OUT_OF_MEMORY; goto cleanup; } ctx->errors_count = 0; ctx->publicationsFile = NULL; ctx->pkiTruststore = NULL; ctx->netProvider = NULL; ctx->publicationCertEmail_DEPRECATED = NULL; ctx->loggerCB = NULL; ctx->requestHeaderCB = NULL; ctx->flags[KSI_CTX_FLAG_AGGR_PDU_VER] = KSI_AGGREGATION_PDU_VERSION; ctx->flags[KSI_CTX_FLAG_EXT_PDU_VER] = KSI_EXTENDING_PDU_VERSION; ctx->loggerCtx = NULL; ctx->certConstraints = NULL; ctx->freeCertConstraintsArray = freeCertConstraintsArray; ctx->lastFailedSignature = NULL; KSI_ERR_clearErrors(ctx); /* Create global cleanup list as the first thing. */ res = KSI_List_new(NULL, &ctx->cleanupFnList); if (res != KSI_OK) goto cleanup; /* Create and set the logger. */ res = KSI_CTX_setLoggerCallback(ctx, KSI_LOG_StreamLogger, stdout); if (res != KSI_OK) goto cleanup; res = KSI_CTX_setLogLevel(ctx, KSI_LOG_NONE); if (res != KSI_OK) goto cleanup; res = KSI_UriClient_new(ctx, &client); if (res != KSI_OK) goto cleanup; res = KSI_CTX_setNetworkProvider(ctx, client); if (res != KSI_OK) goto cleanup; ctx->isCustomNetProvider = 0; client = NULL; /* Initialize truststore. */ res = KSI_PKITruststore_registerGlobals(ctx); if (res != KSI_OK) goto cleanup; /* Return the context. */ *context = ctx; ctx = NULL; res = KSI_OK; cleanup: KSI_NetworkClient_free(client); KSI_CTX_free(ctx); return res; }
static int winINet_ReadFromHandle(KSI_RequestHandle *reqHandle, unsigned char **buf, DWORD *len){ int res = KSI_UNKNOWN_ERROR; HINTERNET handle; KSI_HttpClient *http = NULL; DWORD dwordLen; DWORD http_payload_len = 0; DWORD http_status; DWORD tmp_len = 0; unsigned char *tmp = NULL; KSI_CTX *ctx = NULL; if (reqHandle == NULL || buf == NULL || len == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } ctx = reqHandle->ctx; KSI_ERR_clearErrors(ctx); handle = ((wininetNetHandleCtx*)reqHandle->implCtx)->request_handle; http = (KSI_HttpClient*)reqHandle->client; /*Get HTTP status code*/ dwordLen = sizeof(DWORD); if (!HttpQueryInfo(handle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &http_status, &dwordLen, 0)) { WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.") WININET_ERROR_m(ctx, ERROR_HTTP_HEADER_NOT_FOUND, KSI_NETWORK_ERROR, "WinINet: HTTP status code header not found.") WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: Unable to get HTTP status code.") } http->httpStatus = http_status; /*Get the length of the payload*/ dwordLen = sizeof(DWORD); if (!HttpQueryInfo(handle, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &http_payload_len, &dwordLen, 0)){ WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.") WININET_ERROR_m(ctx, ERROR_HTTP_HEADER_NOT_FOUND, KSI_NETWORK_ERROR, "WinINet: HTTP content length not found.") WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: Unable to get HTTP content length.") } /*Get memory for the HTTP payload*/ tmp_len = http_payload_len; tmp = (unsigned char*)KSI_malloc(tmp_len); if (tmp == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } /*Read data*/ if (!InternetReadFile(handle, tmp, tmp_len, &tmp_len)) { WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.") WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: HTTP Internet read error.") } if (tmp_len != http_payload_len){ KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "WinINet: Unable to read all bytes."); goto cleanup; } *buf = tmp; *len = tmp_len; tmp = NULL; res = KSI_OK; cleanup: KSI_free(tmp); return res; }
static int readResponse(KSI_RequestHandle *handle) { int res; TcpClientCtx *tcp = NULL; KSI_TcpClient *client = NULL; int sockfd = -1; struct sockaddr_in serv_addr; struct hostent *server = NULL; size_t count; unsigned char buffer[0xffff + 4]; KSI_FTLV ftlv; #ifdef _WIN32 DWORD transferTimeout = 0; #else struct timeval transferTimeout; #endif if (handle == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(handle->ctx); tcp = handle->implCtx; client = handle->client->impl; sockfd = (int)socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to open socket."); goto cleanup; } #ifdef _WIN32 transferTimeout = client->transferTimeoutSeconds * 1000; #else transferTimeout.tv_sec = client->transferTimeoutSeconds; transferTimeout.tv_usec = 0; #endif /*Set socket options*/ setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void*)&transferTimeout, sizeof(transferTimeout)); setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void*)&transferTimeout, sizeof(transferTimeout)); server = gethostbyname(tcp->host); if (server == NULL) { KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to open host."); goto cleanup; } memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memmove((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(tcp->port); if ((res = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) { KSI_ERR_push(handle->ctx, KSI_NETWORK_ERROR, res, __FILE__, __LINE__, "Unable to connect."); res = KSI_NETWORK_ERROR; goto cleanup; } KSI_LOG_logBlob(handle->ctx, KSI_LOG_DEBUG, "Sending request", handle->request, handle->request_length); count = 0; while (count < handle->request_length) { int c; #ifdef _WIN32 if (handle->request_length > INT_MAX) { KSI_pushError(handle->ctx, res = KSI_BUFFER_OVERFLOW, "Unable to send more than MAX_INT bytes."); goto cleanup; } c = send(sockfd, (char *) handle->request, (int) handle->request_length, 0); #else c = send(sockfd, (char *) handle->request, handle->request_length, 0); #endif if (c < 0) { KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to write to socket."); goto cleanup; } count += c; } res = KSI_FTLV_socketRead(sockfd, buffer, sizeof(buffer), &count, &ftlv); if (res != KSI_OK || count == 0) { KSI_pushError(handle->ctx, res = KSI_INVALID_ARGUMENT, "Unable to read TLV from socket."); goto cleanup; } if(count > UINT_MAX){ KSI_pushError(handle->ctx, res = KSI_BUFFER_OVERFLOW, "Too much data read from socket."); goto cleanup; } handle->response = KSI_malloc(count); if (handle->response == NULL) { KSI_pushError(handle->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(handle->response, buffer, count); handle->response_length = count; handle->completed = true; res = KSI_OK; cleanup: if (sockfd >= 0) close(sockfd); return res; }