// SignUtils - procedures for PKCS7 signing with CAPICOM

var  CAPICOM_CURRENT_USER_STORE = 2;
var  CAPICOM_STORE_OPEN_READ_ONLY = 0;
var  CAPICOM_ENCODE_BASE64 = 0;
var  CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var  CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var  CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var  CAPICOM_E_CANCELLED  = -2138568446;
var  E_ACTION_CANCELED    = -2146434962;
var  E_KEYSET_NOT_DEFINED = -2146893799;

var  CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var  CAPICOM_VERIFY_SIGNATURE_ONLY = 0;

var  CAPICOM_DETACHED_SIGNATURE = true;

function IsCAPICOMInstalled()
{
	if (typeof(oCAPICOM) == "object")
	{
		if ( (oCAPICOM.object != null) )
		{
			// We found CAPICOM!
			return true;
		}
	}
	
	return false;
}

var PKCS7_BASE64_HEADER = "-----BEGIN PKCS7-----";
var PKCS7_BASE64_FOOTER = "-----END PKCS7-----";

function SignDataCrypto(content, retdata)
{
	var res = crypto.signText(content, "ask");
	
	if (res == 'error:noMatchingCert') {
		return 10;
	} else if (res == 'error:userCancel') {
		return 11;
	} else if (res == 'error:internalError') {
		return 12;
	} else {
		retdata[0] = res;
	}
	
	return 0;
}

// SignData - signs the content parameter
// and returns base64 encoded pkcs7 in retdata
function SignDataCAPICOM(content, retdata)
{
	if (!IsCAPICOMInstalled()) {
		return 1;
	}

	//retdata[0] = "";

	try
	{
		var sd = new ActiveXObject("CAPICOM.SignedData");
	} catch(e)
	{
		return 2;
	}

	try
	{
		var detached_signature = CAPICOM_DETACHED_SIGNATURE;
		
		var signer = new ActiveXObject("CAPICOM.Signer");
		var store = new ActiveXObject("CAPICOM.Store");
		var time_attr = new ActiveXObject("CAPICOM.Attribute");

		store.Open(CAPICOM_CURRENT_USER_STORE, 'MY', CAPICOM_STORE_OPEN_READ_ONLY);

		//find valid certificates for signing
		/*
		var certs = store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_KEY_USAGE,
											CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE, true);
		*/
		var certs = store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID);

		signer.Certificate = certs.Select(msg_sign_certificates, msg_sign_chooseCertificate, false).Item(1);

		//CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME
		time_attr.Name = 0;
		var dat = new Date();
		time_attr.Value = dat.getVarDate();
		signer.AuthenticatedAttributes.Add(time_attr);

		sd.Content = content;
		retdata[0] = sd.Sign(signer, detached_signature, CAPICOM_ENCODE_BASE64);
	} catch(e)
	{
		if ((e.number == CAPICOM_E_CANCELLED) || 
			(e.number == E_ACTION_CANCELED) || 
			(e.number == E_KEYSET_NOT_DEFINED)) {
			return 3; //no cert selected
		} else {
			retdata[0] = e.message;
			return 4;  // signing error
		}
	}

	return 0;
}

// CoSignData - cosigns the given pkcs#7 content
// and returns base64 encoded pkcs7 in retdata
function CoSignDataCAPICOM(pkcs7_content, retdata)
{
	if (!IsCAPICOMInstalled()) {
		return 1;
	}

	//retdata[0] = "";

	try
	{
		var sd = new ActiveXObject("CAPICOM.SignedData");
	} catch(e)
	{
		return 2;
	}

	try
	{
		var detached_signature = CAPICOM_DETACHED_SIGNATURE;
		
		var signer = new ActiveXObject("CAPICOM.Signer");
		var store = new ActiveXObject("CAPICOM.Store");
		var time_attr = new ActiveXObject("CAPICOM.Attribute");
		
		store.Open(CAPICOM_CURRENT_USER_STORE, 'MY', CAPICOM_STORE_OPEN_READ_ONLY);
		
		//find valid certificates for signing
		/*
		var certs = store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_KEY_USAGE,
											CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE, true);
		*/
		var certs = store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID);
		
		signer.Certificate = certs.Select(msg_sign_certificates, msg_sign_chooseCertificate, false).Item(1);
		
		//CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME
		time_attr.Name = 0;
		var dat = new Date();
		time_attr.Value = dat.getVarDate();
		signer.AuthenticatedAttributes.Add(time_attr);
		
		sd.Verify(pkcs7_content, false, CAPICOM_VERIFY_SIGNATURE_ONLY);
		retdata[0] = sd.CoSign(signer, CAPICOM_ENCODE_BASE64);
	} catch(e)
	{
		if ((e.number == CAPICOM_E_CANCELLED) || 
			(e.number == E_ACTION_CANCELED) || 
			(e.number == E_KEYSET_NOT_DEFINED)) {
			return 3; //no cert selected
		} else {
			retdata[0] = e.message;
			return 4;  // signing error
		}
	}

	return 0;
}
