#!/usr/bin/tclsh
lappend auto_path [file dirname [info script]]
package require ossltest
cd $::test::dir
set testname [file rootname [file tail $::argv0]]

start_tests "Тесты на smime -encrypt" 
proc make_fn {alg} {
	return [string map {":" "_"} $alg]
}

proc map {str list} {
	set result {}
	foreach a $list {
		lappend result [subst $str]
	}
	return $result
}	
if {![file exist encrypt.dat]} {
	makeFile encrypt.dat [string repeat "Test data to encrypt.\n" 100] 
}

if {![info exist env(NO_RSA)]} {
test "Creating RSA CA" {
	makeCA ${testname}CA-RSA rsa:512
} 0 1

foreach user {U_enc_rsa_1 U_enc_rsa_2} {
test "Make registered user $user" {
	makeRegisteredUser $user rsa:512 CAname ${testname}CA-RSA
} 0 1
}


test "RSA User 1 encrypts message for RSA user 2" {
	openssl "smime -encrypt -in encrypt.dat -aes-128-cbc -out enc_rsa.msg U_enc_rsa_2/cert.pem"
	file isfile enc_rsa.msg
} 0 1

test "RSA User 1 cannot decrypt message for RSA user 2" {
	grep "Error"	[openssl "smime -decrypt -in enc_rsa.msg -recip U_enc_rsa_1/cert.pem -inkey U_enc_rsa_1/seckey.pem"]
} 1 {Error decrypting PKCS#7 structure}

test -createsfiles decrypt.rsa "RSA User 2 (with cert) can decrypt message for RSA user 2" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -in enc_rsa.msg -recip U_enc_rsa_2/cert.pem -inkey U_enc_rsa_2/seckey.pem -out decrypt.rsa"
	set result [getFile decrypt.rsa]
	string eq $expected $result
} 0 1

test -createsfiles decrypt_nocert.rsa "RSA User 2 (without cert) can decrypt message for RSA user 2" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -in enc_rsa.msg -inkey U_enc_rsa_2/seckey.pem -out decrypt_nocert.rsa"
	set result [getFile decrypt_nocert.rsa]
	string eq $expected $result
} 0 1
}

test "Creating CA 2001" {
	makeCA ${testname}CA gost2001:A
} 0 1

test "Creating CA 2012" {
	makeCA
} 0 1

if {[info exist env(ENC_LIST)]} {
	set enc_list $env(ENC_LIST)
} else {
	switch -exact [engine_name] {
		"ccore" {set enc_list {gost2001:XA:1.2.643.2.2.31.3 gost2001:XB:1.2.643.2.2.31.4 gost2001:XA: gost2012_256:XA:1.2.643.2.2.31.1 gost2012_256:XB:1.2.643.7.1.2.5.1.1 gost2012_256:XA: gost2012_512:A:1.2.643.2.2.31.3 gost2012_512:B:1.2.643.7.1.2.5.1.1 gost2012_512:A:}}
		"open" {set enc_list {gost2001:XA:1.2.643.2.2.31.3 gost2001:XB:1.2.643.2.2.31.4 gost2012_256:XA:1.2.643.2.2.31.1 gost2012_256:XB:1.2.643.7.1.2.5.1.1 gost2012_512:A:1.2.643.2.2.31.3 gost2012_512:B:1.2.643.7.1.2.5.1.1}}
	}
}

foreach enc_tuple $enc_list {
	if {![regexp {^([^:]*:[^:]*):(.*)$} $enc_tuple -> alg crypt_param]} {
		set alg $enc_tuple
		set crypt_param {}
	}
	set alg_fn [make_fn $enc_tuple]
	set username U_enc_$alg_fn
	switch -glob $alg {
		gost2012* {set ::test::ca ${testname}CA-2012}
		* {set ::test::ca ${testname}CA}
	}

test "Creating user $username with key $alg" {
	makeRegisteredUser $username $alg

	if {![file exists $username/req.pem]&&[file exists $username/cert.pem]} {
		file delete $username/cert.pem
	}	
	file exists $username/cert.pem
} 0 1

if {[string length $crypt_param]} {
	set env(CRYPT_PARAMS) $crypt_param
} else {
	if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
}

test -createsfiles enc_$alg_fn.msg "Encrypting for $username" {
	grep "rror" [openssl "smime -encrypt -in encrypt.dat -gost89 -out enc_$alg_fn.msg U_enc_$alg_fn/cert.pem"]
} 0 ""

if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}

test -createsfiles enc_$alg_fn.pem "Extracting PKCS7 from encrypted structure for $username" {
	openssl "smime -pk7out -out enc_$alg_fn.pem -in enc_$alg_fn.msg"
	file isfile enc_$alg_fn.pem
} 0 1

test -skip {![file exists enc_$alg_fn.pem]} "Checking oids in pkcs7 structure for $username" {
	extract_oids enc_$alg_fn.pem PEM
} 0 [mkObjList [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]]  "GOST 28147-89" [encr_long_name $crypt_param]]

test -createsfiles decrypt.$alg_fn "Decrypting file encrypted for $username" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -in enc_$alg_fn.msg -recip U_enc_$alg_fn/cert.pem -inkey U_enc_$alg_fn/seckey.pem -out decrypt.$alg_fn"
	set result [getFile decrypt.$alg_fn]
	string eq $expected $result
} 0 1

if {[string length $crypt_param]} {
	set env(CRYPT_PARAMS) $crypt_param
} else {
	if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
}

test -createsfiles enc_t_$alg_fn.msg "Encrypting for $username - text format" {
	grep "rror" [openssl "smime -encrypt -text -in encrypt.dat -gost89 -out enc_t_$alg_fn.msg U_enc_$alg_fn/cert.pem"]
} 0 ""

if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}

test -createsfiles decrypt_t.$alg_fn "Decrypting file text-encrypted for $username" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -text -in enc_t_$alg_fn.msg -recip U_enc_$alg_fn/cert.pem -inkey U_enc_$alg_fn/seckey.pem -out decrypt_t.$alg_fn"
	set result [getFile decrypt_t.$alg_fn]
	string eq $expected $result
} 0 1

test -createsfiles decrypt_t_nocert.$alg_fn "Decrypting file text-encrypted for $username without cert" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -text -in enc_t_$alg_fn.msg -inkey U_enc_$alg_fn/seckey.pem -out decrypt_t_nocert.$alg_fn"
	set result [getFile decrypt_t_nocert.$alg_fn]
	string eq $expected $result
} 0 1
}

if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}

# FIXME этот тест и парное расшифрование надо прогнать с разными параметрами шифрования
test -createfiles enc_4all "Encrypt for all" {
	grep "rror" [openssl "smime -encrypt -in encrypt.dat -gost89 -out enc_4all.msg [map {U_enc_[make_fn $a]/cert.pem} $enc_list]"]
} 0 ""

foreach enc_tuple $enc_list {
	if {![regexp {^([^:]*:[^:]*):(.*)$} $enc_tuple -> alg crypt_param]} {
		set alg $enc_tuple
		set crypt_param {}
	}
	set alg_fn [make_fn $enc_tuple]
	set username U_enc_$alg_fn
	
test -skip {![file exists enc_4all.msg]} -createsfiles decrypt_4all.$alg_fn "Decrypting gost-encrypted file, recipient $alg_fn" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -in enc_4all.msg -recip $username/cert.pem -inkey $username/seckey.pem -out decrypt_4all.$alg_fn"
	set result [getFile decrypt_4all.$alg_fn]
	string eq $expected $result
} 0 1

test -skip {![file exists enc_4all.msg]} -createsfiles decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
	set expected [getFile encrypt.dat]
	openssl "smime -decrypt -in enc_4all.msg -inkey $username/seckey.pem -out decrypt_4all_nocert.$alg_fn"
	set result [getFile decrypt_4all_nocert.$alg_fn]
	string eq $expected $result
} 0 1
}

restore_env2 {OPENSSL_CONF CRYPT_PARAMS}

end_tests
