Ejemplo n.º 1
0
void CClassCommon::InitArgsSKFImportCerts(VARIANT aArrayArgIN)
{
	int inBuffSize  = 0;

	unsigned char data_value_cert_b64[BUFFER_LEN_1K * 4]; 
	unsigned long data_len_cert_b64 = BUFFER_LEN_1K * 4;

	GetArrayLength(aArrayArgIN.pdispVal,&inBuffSize);

	::FILE_LOG_STRING(file_log_name, __FUNCTION__);

	::FILE_LOG_NUMBER(file_log_name, inBuffSize);

	if (3 != inBuffSize)
	{
		ulResult = OPE_ERR_INVALID_PARAM;
		return;
	}

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,0, m_szPIN, &m_iPINLen);

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,1, (char *)data_value_cert_b64,(int *) (&data_len_cert_b64));

	m_iCertSIGNLen = modp_b64_decode((char *)m_szCertSIGN, (char *)data_value_cert_b64,data_len_cert_b64);

	data_len_cert_b64 = BUFFER_LEN_1K * 4;

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,2, (char *)data_value_cert_b64,(int *) (&data_len_cert_b64));

	m_iCertEXLen = modp_b64_decode((char *)m_szCertEX, (char *)data_value_cert_b64,data_len_cert_b64);

	ulResult = 0;
}
Ejemplo n.º 2
0
static char* testDecodeErrors(void)
{
    int i;
    size_t y;
    char out[1000];
    char decode[5];
    char msg[100];

    /* negative length */
    memset(decode, 1, sizeof(decode));
    y = modp_b64_decode(out, decode, (size_t)-1);
    mu_assert_int_equals(-1, y);

    /* test bad input -  all combinations */
    char goodchar = 'A';
    char badchar = '~';
    for (i = 1; i < 16; ++i) {
        decode[0] = (char)(((i & 0x01) == 0) ? goodchar : badchar);
        decode[1] = (char)(((i & 0x02) == 0) ? goodchar : badchar);
        decode[2] = (char)(((i & 0x04) == 0) ? goodchar : badchar);
        decode[3] = (char)(((i & 0x08) == 0) ? goodchar : badchar);
        decode[4] = '\0';

        sprintf(msg, "i = %d, %s", i, decode);
        y = modp_b64_decode(out, decode, (size_t)4);
        mu_assert_int_equals_msg(msg, (size_t)-1, y);
    }


    /*  test just 1-4 padchars */
    for (i = 0; i < 4; ++i) {
        decode[i] = '=';
        decode[i+1] = '\0';
        y = modp_b64_decode(out, decode, (size_t)(i+1));
        sprintf(msg, "i=%d, b64=%s", i, decode);
        mu_assert_int_equals_msg(msg, (size_t)-1, y);
    }

    /* Test good+3 pad chars (should be impossible) */
    decode[0] = 'A';
    decode[1] = '=';
    decode[2] = '=';
    decode[3] = '=';
    y = modp_b64_decode(out, decode, (size_t)4);
    mu_assert_int_equals(-1, y);

    return 0;
}
Ejemplo n.º 3
0
static void frame_callback(const char *frame_data, size_t len, void *userdata)
{
	size_t image_len;
	char *image;
	struct json_internal *json = userdata;

	if (!json)
		return;

	if (frame_data && len) {
		/* 'image' should be freed by the client */
		image_len = modp_b64_decode_len(len);
		image = ec_malloc(image_len);
		image_len = modp_b64_decode(image, frame_data, len);

		if (image_len != -1)
			json->frame_callback(image, image_len, json->userdata);
		else
			goto fail;

		/* Success! */
		return;
	}

fail:
	/*
	 * Failure
	 * If image decoding failed, call frame_callback() with a NULL argument,
	 * to let the client know about the error.
	 */
	json->frame_callback(NULL, 0, json->userdata);

}
Ejemplo n.º 4
0
void CClassCommon::InitArgsSM2Keys(VARIANT aArrayArgIN)
{
	int inBuffSize  = 0;

	unsigned char data_value_key_b64[BUFFER_LEN_1K * 4]; 
	unsigned long data_len_key_b64 = BUFFER_LEN_1K * 4;

	unsigned char data_value_key[BUFFER_LEN_1K * 4]; 
	unsigned long data_len_key = BUFFER_LEN_1K * 4;

	GetArrayLength(aArrayArgIN.pdispVal,&inBuffSize);

	::FILE_LOG_STRING(file_log_name, __FUNCTION__);

	::FILE_LOG_STRING(file_log_name, "START");

	::FILE_LOG_NUMBER(file_log_name, inBuffSize);

	if (3 != inBuffSize)
	{
		ulResult = OPE_ERR_INVALID_PARAM;
		return;
	}

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,0, (char *)data_value_key_b64,(int *) (&data_len_key_b64));

	data_len_key = modp_b64_decode((char *)data_value_key, (char *)data_value_key_b64,data_len_key);

	::FILE_LOG_STRING(file_log_name, "data_len_key");

	::FILE_LOG_NUMBER(file_log_name, data_len_key);

	::FILE_LOG_HEX(file_log_name, data_value_key,data_len_key);

	if (sizeof(OPST_PCI_ECCrefPublicKey) + sizeof(OPST_PCI_ECCrefPrivateKey) != data_len_key)
	{
		ulResult = OPE_ERR_INVALID_PARAM;
		return;
	}

	::FILE_LOG_STRING(file_log_name, "SM2KEYS");
	::FILE_LOG_HEX(file_log_name,data_value_key, data_len_key);

	memcpy(&m_stPublicKey,data_value_key,sizeof(OPST_PCI_ECCrefPublicKey));
	memcpy(&m_stPrivateKey,data_value_key + sizeof(OPST_PCI_ECCrefPublicKey), sizeof(OPST_PCI_ECCrefPrivateKey));

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,1, m_szPIN, &m_iPINLen);

	GetArrayNumberOfIndex(aArrayArgIN.pdispVal,2,&ulContype);

	::FILE_LOG_STRING(file_log_name, __FUNCTION__);

	::FILE_LOG_STRING(file_log_name, "END");

	ulResult = 0;
}
Ejemplo n.º 5
0
    static bool Base64Decode(const std::string& input, std::string* output)
    {
        std::string temp;
        temp.resize(modp_b64_decode_len(input.size()));

        int input_size = static_cast<int>(input.size());
        int output_size = modp_b64_decode(&(temp[0]), input.data(), input_size);
        if (output_size < 0)
            return false;

        temp.resize(output_size);
        output->swap(temp);
        return true;
    }
Ejemplo n.º 6
0
bool Base64Decode(const std::string& input, std::string* output) {
  std::string temp;
  temp.resize(modp_b64_decode_len(input.size()));

  // does not null terminate result since result is binary data!
  int input_size = static_cast<int>(input.size());
  int output_size = modp_b64_decode(&(temp[0]), input.data(), input_size);
  if (output_size < 0)
    return false;

  temp.resize(output_size);
  output->swap(temp);
  return true;
}
Ejemplo n.º 7
0
string EasyUtil::Base64Decode(const string &sInput)
{
	std::string temp;
	temp.resize(modp_b64_decode_len(sInput.size()));

	// does not null terminate result since result is binary data!
	int input_size = static_cast<int>(sInput.size());
	int output_size = modp_b64_decode(&(temp[0]), sInput.data(), input_size);
	if (output_size < 0)
		return false;

	temp.resize(output_size);

	return temp;
}
Ejemplo n.º 8
0
/**
 * sending 0 as length to encode and decode
 * should basically do nothing
 */
static char* testEmpty(void)
{
    char buf[10];
    const char* input = 0; /* null */
    size_t d;

    memset(buf, 1, sizeof(buf));
    d = modp_b64_encode(buf, input, (size_t)0);
    mu_assert_int_equals(0, d);
    mu_assert_int_equals(0, buf[0]);
    mu_assert_int_equals(1, buf[1]);

    memset(buf, 1, sizeof(buf));
    d = modp_b64_decode(buf, input, (size_t)0);
    mu_assert_int_equals(0, d);
    mu_assert_int_equals(1, buf[0]);
    mu_assert_int_equals(1, buf[1]);

    return 0;
}
Ejemplo n.º 9
0
// 初始化交换数字信封
void CClassCommon::InitArgsSKFImportSM2KeyPair(VARIANT aArrayArgIN)
{
	int inBuffSize  = 0;

	unsigned char szEnvelopedKeyBlobB64[BUFFER_LEN_1K * 4]; 
	unsigned long ulEnvelopedKeyBlobB64Len = BUFFER_LEN_1K * 4;
	unsigned long ulEnvelopedKeyBlobLen = BUFFER_LEN_1K * 4;

	GetArrayLength(aArrayArgIN.pdispVal,&inBuffSize);

	::FILE_LOG_STRING(file_log_name, __FUNCTION__);

	::FILE_LOG_STRING(file_log_name, "START");

	::FILE_LOG_NUMBER(file_log_name, inBuffSize);

	if (2 != inBuffSize)
	{
		ulResult = OPE_ERR_INVALID_PARAM;
		return;
	}

	GetArrayStrOfIndex(aArrayArgIN.pdispVal,0, m_szPIN, &m_iPINLen);
	GetArrayStrOfIndex(aArrayArgIN.pdispVal,1, (char *)szEnvelopedKeyBlobB64,(int *)(&ulEnvelopedKeyBlobB64Len));

	ulEnvelopedKeyBlobLen = modp_b64_decode((char *)&m_stEnvelopedKeyBlobEX, (const char *)szEnvelopedKeyBlobB64,ulEnvelopedKeyBlobB64Len);

	::FILE_LOG_STRING(file_log_name, "m_stEnvelopedKeyBlobEX");

	::FILE_LOG_HEX(file_log_name, (const unsigned char *)&m_stEnvelopedKeyBlobEX,sizeof(OPST_SKF_ENVELOPEDKEYBLOB));

	if (sizeof(OPST_SKF_ENVELOPEDKEYBLOB) != ulEnvelopedKeyBlobLen)
	{
		::FILE_LOG_STRING(file_log_name, "sizeof(OPST_SKF_ENVELOPEDKEYBLOB) != ulEnvelopedKeyBlobLen");
		ulResult = OPE_ERR_INVALID_PARAM;
		return;
	}

	ulResult = 0;
}
Ejemplo n.º 10
0
/**
 * checks to make sure results are the same reguardless of
 * CPU endian type (i.e. Intel vs. Sparc, etc)
 *
 */
static char* testEndian(void)
{
    /* this test that "1" is "AAAB" */
    char buf[100];
    char result[10];
    char endian[] = { (char)0, (char)0, (char)1 };
    size_t d = modp_b64_encode(buf, endian, (size_t)3);
    mu_assert_int_equals(4, d);
    mu_assert_int_equals('A', buf[0]);
    mu_assert_int_equals('A', buf[1]);
    mu_assert_int_equals('A', buf[2]);
    mu_assert_int_equals('B', buf[3]);

    memset(result, 255, sizeof(result));
    d = modp_b64_decode(result, "AAAB", (size_t)4);
    mu_assert_int_equals(3, d);
    mu_assert_int_equals(0, result[0]);
    mu_assert_int_equals(0, result[1]);
    mu_assert_int_equals(1, result[2]);
    mu_assert_int_equals(-1, result[3]);

    return 0;
}
Ejemplo n.º 11
0
/**
 * Test all 17M 3 bytes inputs to encoder, decode
 * and make sure it's equal.
 */
static char* testEncodeDecode(void)
{
    char ibuf[4];
    char obuf[5];
    char rbuf[4];
    char msg[100];
    msg[0] = 0; /* make msg an empty string */
    unsigned int i, j, k;
    size_t d = 0;
    for (i = 0; i < 256; ++i) {
        for (j = 0; j < 256; ++j) {
            for (k = 0; k < 256; ++k) {
                /* comment this out.. it really slows down the test */
                /* sprintf(msg, "(i,j,k) = (%d,%d,%d):", i,j,k); */
                ibuf[0] = (char)((unsigned char)i);
                ibuf[1] = (char)((unsigned char)j);
                ibuf[2] = (char)((unsigned char)k);
                ibuf[3] = 0;

                memset(obuf, 1, sizeof(obuf));
                d = modp_b64_encode(obuf, ibuf, (size_t)3);
                mu_assert_int_equals_msg(msg, 4, d);
                mu_assert_int_equals_msg(msg, 0, obuf[4]);

                memset(rbuf, 1, sizeof(rbuf));
                d = modp_b64_decode(rbuf, obuf, (size_t)4);
                mu_assert_int_equals_msg(msg, 3, d);
                mu_assert_int_equals_msg(msg, ibuf[0], rbuf[0]);
                mu_assert_int_equals_msg(msg, ibuf[1], rbuf[1]);
                mu_assert_int_equals_msg(msg, ibuf[2], rbuf[2]);
                mu_assert_int_equals_msg(msg, 1, rbuf[3]);
            }
        }
    }
    return 0;
}
Ejemplo n.º 12
0
/**
 * Test 1-6 bytes input and decode
 *
 */
static char* testPadding(void)
{
    char msg[100];
    const char ibuf[6] = { 1, 1, 1, 1, 1, 1 };
    char obuf[10];
    char rbuf[10];
    size_t d = 0;

    /* 1 in, 4 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)1);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 4, d);
    mu_assert_int_equals_msg(msg, 0, obuf[4]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals_msg(msg, 1, d);
    mu_assert_int_equals(1, rbuf[0]);
    mu_assert_int_equals(-1, rbuf[1]);

    /* 2 in, 4 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)2);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 4, d);
    mu_assert_int_equals_msg(msg, 0, obuf[4]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals_msg(msg, 2, d);
    mu_assert_int_equals_msg(msg, 1, rbuf[0]);
    mu_assert_int_equals_msg(msg, 1, rbuf[1]);
    mu_assert_int_equals_msg(msg, -1, rbuf[2]);

    /* 3 in, 4 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)3);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 4, d);
    mu_assert_int_equals_msg(msg, 0, obuf[4]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals_msg(msg, 3, d);
    mu_assert_int_equals_msg(msg, 1, rbuf[0]);
    mu_assert_int_equals_msg(msg, 1, rbuf[1]);
    mu_assert_int_equals_msg(msg, 1, rbuf[2]);
    mu_assert_int_equals_msg(msg, -1, rbuf[3]);

    /* 4 in, 8 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)4);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 8, d);
    mu_assert_int_equals_msg(msg, 0, obuf[8]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals(4, d);
    mu_assert_int_equals(1, rbuf[0]);
    mu_assert_int_equals(1, rbuf[1]);
    mu_assert_int_equals(1, rbuf[2]);
    mu_assert_int_equals(1, rbuf[3]);
    mu_assert_int_equals(-1, rbuf[4]);

    /* 5 in, 8 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)5);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 8, d);
    mu_assert_int_equals_msg(msg, 0, obuf[8]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals(5, d);
    mu_assert_int_equals(1, rbuf[0]);
    mu_assert_int_equals(1, rbuf[1]);
    mu_assert_int_equals(1, rbuf[2]);
    mu_assert_int_equals(1, rbuf[3]);
    mu_assert_int_equals(1, rbuf[4]);
    mu_assert_int_equals(-1, rbuf[5]);

    /* 6 in, 8 out */
    memset(obuf, 255, sizeof(obuf));
    d = modp_b64_encode(obuf, ibuf, (size_t)6);
    sprintf(msg, "b64='%s', d=%d", obuf, (int)d);
    mu_assert_int_equals_msg(msg, 8, d);
    mu_assert_int_equals_msg(msg, 0, obuf[8]);
    memset(rbuf, 255, sizeof(rbuf));
    d = modp_b64_decode(rbuf, obuf, d);
    mu_assert_int_equals(6, d);
    mu_assert_int_equals(1, rbuf[0]);
    mu_assert_int_equals(1, rbuf[1]);
    mu_assert_int_equals(1, rbuf[2]);
    mu_assert_int_equals(1, rbuf[3]);
    mu_assert_int_equals(1, rbuf[4]);
    mu_assert_int_equals(1, rbuf[5]);
    mu_assert_int_equals(-1, rbuf[6]);

    return 0;
}
Ejemplo n.º 13
0
int VerifyDataSignWithHashAlg(const char * userData,  const char * hashAlg, const char * certDataB64, const char * signatureDataB64)
{
	int rv = -1;
	int ulHashAlg = 0;
	HCRYPTHASH hHash = NULL;
	char * pbCert = NULL;
	char * pbSignature = NULL;
	unsigned int ulCert = 0;
	unsigned int ulSignature = 0;
	PCCERT_CONTEXT pCertContext = NULL;  
	HCRYPTPROV hProv = NULL;  
	HCRYPTKEY hPubKey = NULL;  

	{
		ulCert = modp_b64_decode_len(strlen(certDataB64));
		ulSignature = modp_b64_decode_len(strlen(signatureDataB64));

		pbCert = (char *)malloc(ulCert);
		pbSignature =  (char *) malloc(ulSignature);

		if (NULL == pbCert || NULL == pbSignature)
		{
			sprintf(m_errMsg, "%s","memroy less.\n" );
			goto err;
		}

		ulCert = modp_b64_decode(pbCert, certDataB64,strlen(certDataB64));
		ulSignature = modp_b64_decode(pbSignature, signatureDataB64,strlen(signatureDataB64));
	}

	if (0 == strcmp(hashAlg, "MD5"))
	{
		ulHashAlg = CALG_MD5;
	}
	else if (0 == strcmp(hashAlg, "SHA"))
	{
		ulHashAlg = CALG_SHA;
	}
	else if (0 == strcmp(hashAlg, "SHA1"))
	{
		ulHashAlg = CALG_SHA1;
	}
	else if (0 == strcmp(hashAlg, "SHA_256"))
	{
		ulHashAlg = CALG_SHA_256;
	}
	else if (0 == strcmp(hashAlg, "SHA_384"))
	{
		ulHashAlg = CALG_SHA_384;
	}

	pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (BYTE *)pbCert,ulCert);
	if (!pCertContext)
	{
		sprintf(m_errMsg, "%s","Select Certificate UI failed.\n" );
		goto err;
	}


	//Ò»¡¢»ñµÃÒ»¸öCSP¾ä±ú  
	if(!CryptAcquireContext(  
		&hProv,  
		NULL,           //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷  
		NULL,           //CSP_NAME  
		PROV_RSA_FULL,  
		0  
		)) 
	{  
		if(!CryptAcquireContext(  
			&hProv,  
			NULL,           //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷  
			NULL,           //CSP_NAME  
			PROV_RSA_FULL,  
			CRYPT_NEWKEYSET //´´½¨ÃÜÔ¿ÈÝÆ÷  
			))
		{
			sprintf(m_errMsg, "%s","CryptAcquireContext fail.\n");
			goto err;
		}
	}  


	if(CryptImportPublicKeyInfo(
		hProv,
		X509_ASN_ENCODING,
		&(pCertContext->pCertInfo->SubjectPublicKeyInfo),
		&hPubKey
		))
	{
		sprintf(m_errMsg,"CryptImportPublicKeyInfo OK. \n");
	}
	else
	{
		sprintf(m_errMsg,"Error CryptImportPublicKeyInfo.\n");
		goto err;
	}

	//if(CryptImportKey(hProv,pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, NULL, 0, &hPubKey))
	//{
	//	sprintf(m_errMsg,"CryptImportKey OK. \n");
	//}
	//else
	//{
	//	sprintf(m_errMsg,"Error CryptImportKey.\n");
	//	goto err;
	//}

	if(CryptCreateHash(
		hProv, 
		ulHashAlg, 
		0, 
		0, 
		&hHash)) 
	{
		sprintf(m_errMsg, "%s","An empty hash object has been created. \n");
	}
	else
	{
		sprintf(m_errMsg, "%s","Error during CryptBeginHash!\n");
		goto err;
	}


	//--------------------------------------------------------------------
	//  This code assumes that the handle of a cryptographic context 
	//  has been acquired and that a hash object has been created 
	//  and its handle (hHash) is available.
	if(CryptHashData(
		hHash, 
		(unsigned char *)userData, 
		strlen(userData), 
		0)) 
	{
		sprintf(m_errMsg, "%s","The data buffer has been added to the hash.\n");
	}
	else
	{
		sprintf(m_errMsg, "%s","Error during CryptHashData.\n");
		goto err;
	}

	if(CryptVerifySignature(hHash, (const BYTE *)pbSignature, ulSignature,hPubKey,NULL,0))
	{
		sprintf(m_errMsg,"verify OK.\n");
	}
	else
	{
		sprintf(m_errMsg,"Error during CryptVerifySignature.\n");
		goto err;
	}

	rv = 0;

err:
	if(hHash) 
	{
		CryptDestroyHash(hHash);
	}

	if (pbSignature)
	{
		free(pbSignature);
	}

	if (pbCert)
	{
		free(pbCert);
	}

	if (pCertContext)
	{
		CertFreeCertificateContext(pCertContext);
	}

	if(hProv)  
	{
		CryptReleaseContext(hProv,0);  
	}


	return rv;
}
Ejemplo n.º 14
0
unsigned int
Controller::determineHeaderSizeForSessionProtocol(Request *req,
	SessionProtocolWorkingState &state, string delta_monotonic)
{
	unsigned int dataSize = sizeof(boost::uint32_t);

	state.path        = req->getPathWithoutQueryString();
	state.hasBaseURI  = req->options.baseURI != P_STATIC_STRING("/")
		&& startsWith(state.path, req->options.baseURI);
	if (state.hasBaseURI) {
		state.path = state.path.substr(req->options.baseURI.size());
		if (state.path.empty()) {
			state.path = P_STATIC_STRING("/");
		}
	}
	state.queryString = req->getQueryString();
	state.methodStr   = StaticString(http_method_str(req->method));
	state.remoteAddr  = req->secureHeaders.lookup(REMOTE_ADDR);
	state.remotePort  = req->secureHeaders.lookup(REMOTE_PORT);
	state.remoteUser  = req->secureHeaders.lookup(REMOTE_USER);
	state.contentType   = req->headers.lookup(HTTP_CONTENT_TYPE);
	if (req->hasBody()) {
		state.contentLength = req->headers.lookup(HTTP_CONTENT_LENGTH);
	} else {
		state.contentLength = NULL;
	}
	if (req->envvars != NULL) {
		size_t len = modp_b64_decode_len(req->envvars->size);
		state.environmentVariablesData = (char *) malloc(len);
		if (state.environmentVariablesData == NULL) {
			throw RuntimeException("Unable to allocate memory for base64 "
				"decoding of environment variables");
		}
		len = modp_b64_decode(state.environmentVariablesData,
			req->envvars->start->data,
			req->envvars->size);
		if (len == (size_t) -1) {
			throw RuntimeException("Unable to base64 decode environment variables");
		}
		state.environmentVariablesSize = len;
	}

	dataSize += sizeof("REQUEST_URI");
	dataSize += req->path.size + 1;

	dataSize += sizeof("PATH_INFO");
	dataSize += state.path.size() + 1;

	dataSize += sizeof("SCRIPT_NAME");
	if (state.hasBaseURI) {
		dataSize += req->options.baseURI.size();
	} else {
		dataSize += sizeof("");
	}

	dataSize += sizeof("QUERY_STRING");
	dataSize += state.queryString.size() + 1;

	dataSize += sizeof("REQUEST_METHOD");
	dataSize += state.methodStr.size() + 1;

	if (req->host != NULL && req->host->size > 0) {
		const LString *host = psg_lstr_make_contiguous(req->host, req->pool);
		const char *sep = (const char *) memchr(host->start->data, ':', host->size);
		if (sep != NULL) {
			state.serverName = StaticString(host->start->data, sep - host->start->data);
			state.serverPort = StaticString(sep + 1,
				host->start->data + host->size - sep - 1);
		} else {
			state.serverName = StaticString(host->start->data, host->size);
			if (req->https) {
				state.serverPort = P_STATIC_STRING("443");
			} else {
				state.serverPort = P_STATIC_STRING("80");
			}
		}
	} else {
		state.serverName = defaultServerName;
		state.serverPort = defaultServerPort;
	}

	dataSize += sizeof("SERVER_NAME");
	dataSize += state.serverName.size() + 1;

	dataSize += sizeof("SERVER_PORT");
	dataSize += state.serverPort.size() + 1;

	dataSize += sizeof("SERVER_SOFTWARE");
	dataSize += serverSoftware.size() + 1;

	dataSize += sizeof("SERVER_PROTOCOL");
	dataSize += sizeof("HTTP/1.1");

	dataSize += sizeof("REMOTE_ADDR");
	if (state.remoteAddr != NULL) {
		dataSize += state.remoteAddr->size + 1;
	} else {
		dataSize += sizeof("127.0.0.1");
	}

	dataSize += sizeof("REMOTE_PORT");
	if (state.remotePort != NULL) {
		dataSize += state.remotePort->size + 1;
	} else {
		dataSize += sizeof("0");
	}

	if (state.remoteUser != NULL) {
		dataSize += sizeof("REMOTE_USER");
		dataSize += state.remoteUser->size + 1;
	}

	if (state.contentType != NULL) {
		dataSize += sizeof("CONTENT_TYPE");
		dataSize += state.contentType->size + 1;
	}

	if (state.contentLength != NULL) {
		dataSize += sizeof("CONTENT_LENGTH");
		dataSize += state.contentLength->size + 1;
	}

	dataSize += sizeof("PASSENGER_CONNECT_PASSWORD");
	dataSize += ApplicationPool2::ApiKey::SIZE + 1;

	if (req->https) {
		dataSize += sizeof("HTTPS");
		dataSize += sizeof("on");
	}

	if (req->options.analytics) {
		dataSize += sizeof("PASSENGER_TXN_ID");
		dataSize += req->options.transaction->getTxnId().size() + 1;

		dataSize += sizeof("PASSENGER_DELTA_MONOTONIC");
		dataSize += delta_monotonic.size() + 1;
	}

	if (req->upgraded()) {
		dataSize += sizeof("HTTP_CONNECTION");
		dataSize += sizeof("upgrade");
	}

	ServerKit::HeaderTable::Iterator it(req->headers);
	while (*it != NULL) {
		dataSize += sizeof("HTTP_") - 1 + it->header->key.size + 1;
		dataSize += it->header->val.size + 1;
		it.next();
	}

	if (state.environmentVariablesData != NULL) {
		dataSize += state.environmentVariablesSize;
	}

	return dataSize + 1;
}