]> www.wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
tcl_tests: Add TCL tests files
authorDmitry Belyavskiy <beldmit@gmail.com>
Sun, 10 Nov 2019 01:30:14 +0000 (04:30 +0300)
committerDmitry Belyavskiy <beldmit@users.noreply.github.com>
Sat, 11 Jan 2020 21:20:37 +0000 (00:20 +0300)
All source files are converted from cp1251 to utf-8.

132 files changed:
tcl_tests/097.ciphers [new file with mode: 0644]
tcl_tests/098.ciphers [new file with mode: 0644]
tcl_tests/_exists [new file with mode: 0644]
tcl_tests/aes0.enc [new file with mode: 0644]
tcl_tests/aes1.enc [new file with mode: 0644]
tcl_tests/apache.try [new file with mode: 0644]
tcl_tests/asn.tcl [new file with mode: 0644]
tcl_tests/base64.tcl [new file with mode: 0644]
tcl_tests/ca.try [new file with mode: 0644]
tcl_tests/calchash.tcl [new file with mode: 0755]
tcl_tests/calcstat [new file with mode: 0644]
tcl_tests/cbc0.enc [new file with mode: 0644]
tcl_tests/cbc1.enc [new file with mode: 0644]
tcl_tests/cfb0.enc [new file with mode: 0644]
tcl_tests/cfb1.enc [new file with mode: 0644]
tcl_tests/ciphers.try [new file with mode: 0644]
tcl_tests/client.try [new file with mode: 0644]
tcl_tests/cms.try [new file with mode: 0644]
tcl_tests/cms2.try [new file with mode: 0644]
tcl_tests/cms_cs.try [new file with mode: 0644]
tcl_tests/cms_io.try [new file with mode: 0644]
tcl_tests/cmsenc.try [new file with mode: 0644]
tcl_tests/cmsenc_cs.try [new file with mode: 0644]
tcl_tests/cmsenc_io.try [new file with mode: 0644]
tcl_tests/cmsenc_sc.try [new file with mode: 0644]
tcl_tests/cmstc262019.try [new file with mode: 0644]
tcl_tests/cnt0.enc [new file with mode: 0644]
tcl_tests/cnt1.enc [new file with mode: 0644]
tcl_tests/cp10.ciphers [new file with mode: 0644]
tcl_tests/cp20.ciphers [new file with mode: 0644]
tcl_tests/cp21.ciphers [new file with mode: 0644]
tcl_tests/csp3.ciphers [new file with mode: 0644]
tcl_tests/csp36.ciphers [new file with mode: 0644]
tcl_tests/csp36r2.ciphers [new file with mode: 0644]
tcl_tests/csp36r3.ciphers [new file with mode: 0644]
tcl_tests/csp36r4.ciphers [new file with mode: 0644]
tcl_tests/csp39.ciphers [new file with mode: 0644]
tcl_tests/csp4.ciphers [new file with mode: 0644]
tcl_tests/csp4r2.ciphers [new file with mode: 0644]
tcl_tests/csp4r3.ciphers [new file with mode: 0644]
tcl_tests/csp5.ciphers [new file with mode: 0644]
tcl_tests/dgst.try [new file with mode: 0644]
tcl_tests/dgst_CF.dat [new file with mode: 0644]
tcl_tests/dgst_ex1.dat [new file with mode: 0644]
tcl_tests/dgst_ex2.dat [new file with mode: 0644]
tcl_tests/enc.try [new file with mode: 0644]
tcl_tests/engine.try [new file with mode: 0644]
tcl_tests/enums.tcl [new file with mode: 0644]
tcl_tests/getengine.tcl [new file with mode: 0644]
tcl_tests/http.tcl [new file with mode: 0644]
tcl_tests/hwkeys.tcl [new file with mode: 0644]
tcl_tests/interop.try [new file with mode: 0644]
tcl_tests/kbstrike.exe [new file with mode: 0755]
tcl_tests/key.pem [new file with mode: 0644]
tcl_tests/mac-grasshopper.dat [new file with mode: 0644]
tcl_tests/mac-magma.dat [new file with mode: 0644]
tcl_tests/mac.try [new file with mode: 0644]
tcl_tests/macpkm1.enc [new file with mode: 0644]
tcl_tests/magma1.enc [new file with mode: 0644]
tcl_tests/magma_acpkm_plain.enc [new file with mode: 0644]
tcl_tests/magma_enc [new file with mode: 0644]
tcl_tests/magma_plain [new file with mode: 0644]
tcl_tests/magma_plain.enc [new file with mode: 0644]
tcl_tests/make_other.sh [new file with mode: 0755]
tcl_tests/mkn2o.tcl [new file with mode: 0644]
tcl_tests/mkoidf.tcl [new file with mode: 0644]
tcl_tests/name2oid.tcl [new file with mode: 0644]
tcl_tests/name2oid.tst [new file with mode: 0644]
tcl_tests/nopath.try [new file with mode: 0644]
tcl_tests/ocsp.try [new file with mode: 0644]
tcl_tests/oidfile [new file with mode: 0644]
tcl_tests/opnssl.sh [new file with mode: 0755]
tcl_tests/ossltest.tcl [new file with mode: 0644]
tcl_tests/pkcs12.try [new file with mode: 0644]
tcl_tests/pkcs7.tcl [new file with mode: 0644]
tcl_tests/pkcs8.try [new file with mode: 0644]
tcl_tests/pkgIndex.tcl [new file with mode: 0644]
tcl_tests/plain.enc [new file with mode: 0644]
tcl_tests/private/gost2001_A.pem [new file with mode: 0644]
tcl_tests/private/gost2001_B.pem [new file with mode: 0644]
tcl_tests/private/gost2001_C.pem [new file with mode: 0644]
tcl_tests/private/gost2001_XA.pem [new file with mode: 0644]
tcl_tests/private/gost2001_XB.pem [new file with mode: 0644]
tcl_tests/private/gost2012_256_A.pem [new file with mode: 0644]
tcl_tests/private/gost2012_256_B.pem [new file with mode: 0644]
tcl_tests/private/gost2012_256_C.pem [new file with mode: 0644]
tcl_tests/private/gost2012_256_XA.pem [new file with mode: 0644]
tcl_tests/private/gost2012_256_XB.pem [new file with mode: 0644]
tcl_tests/private/gost2012_512_A.pem [new file with mode: 0644]
tcl_tests/private/gost2012_512_B.pem [new file with mode: 0644]
tcl_tests/private/rsa_1024.pem [new file with mode: 0644]
tcl_tests/req-genpkey.try [new file with mode: 0644]
tcl_tests/req-newkey.try [new file with mode: 0644]
tcl_tests/runtest.bat [new file with mode: 0755]
tcl_tests/runtest.sh [new file with mode: 0644]
tcl_tests/runtest1.bat [new file with mode: 0755]
tcl_tests/runtest2.bat [new file with mode: 0755]
tcl_tests/server.try [new file with mode: 0644]
tcl_tests/smime.try [new file with mode: 0644]
tcl_tests/smime2.try [new file with mode: 0644]
tcl_tests/smime_cs.try [new file with mode: 0644]
tcl_tests/smime_io.try [new file with mode: 0644]
tcl_tests/smimeenc.try [new file with mode: 0644]
tcl_tests/smimeenc_io.try [new file with mode: 0644]
tcl_tests/ssl.try [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_keyagree_a211.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_keyagree_a221.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_keytrans_a231.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_keytrans_a241.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_kuznyechik_a421.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encrypted_magma_a411.pem [new file with mode: 0644]
tcl_tests/tc26_cms/encryption_key.hex [new file with mode: 0644]
tcl_tests/tc26_cms/hashed_a311.pem [new file with mode: 0644]
tcl_tests/tc26_cms/hashed_a321.pem [new file with mode: 0644]
tcl_tests/tc26_cms/recipient256_cert.pem [new file with mode: 0644]
tcl_tests/tc26_cms/recipient256_key.pem [new file with mode: 0644]
tcl_tests/tc26_cms/recipient512_cert.pem [new file with mode: 0644]
tcl_tests/tc26_cms/recipient512_key.pem [new file with mode: 0644]
tcl_tests/tc26_cms/root256_cert.pem [new file with mode: 0644]
tcl_tests/tc26_cms/root256_key.pem [new file with mode: 0644]
tcl_tests/tc26_cms/sender256_cert.pem [new file with mode: 0644]
tcl_tests/tc26_cms/sender256_key.pem [new file with mode: 0644]
tcl_tests/tc26_cms/sender512_cert.pem [new file with mode: 0644]
tcl_tests/tc26_cms/sender512_key.pem [new file with mode: 0644]
tcl_tests/tc26_cms/signed_a111.pem [new file with mode: 0644]
tcl_tests/tc26_cms/signed_a121.pem [new file with mode: 0644]
tcl_tests/test.tcl [new file with mode: 0644]
tcl_tests/tmpl.try [new file with mode: 0644]
tcl_tests/ts.try [new file with mode: 0644]
tcl_tests/vn4.ciphers [new file with mode: 0644]
tcl_tests/wcli.try [new file with mode: 0644]
tcl_tests/yarrowc.tcl [new file with mode: 0644]

diff --git a/tcl_tests/097.ciphers b/tcl_tests/097.ciphers
new file mode 100644 (file)
index 0000000..1a33a23
--- /dev/null
@@ -0,0 +1,11 @@
+rsa:1024 {
+       DHE-RSA-AES256-SHA      tls-ref-097.lan.cryptocom.ru:443
+       SSLv2:DES-CBC3-MD5 tls-ref-097.lan.cryptocom.ru:4402
+       SSLv3:DES-CBC-SHA tls-ref-097.lan.cryptocom.ru:4403
+       RC4-SHA tls-ref-097.lan.cryptocom.ru:4404
+}
+
+dsa:dsaparams.pem {
+       DHE-DSS-AES256-SHA  tls-ref-097.lan.cryptocom.ru:444
+       SSLv3:EDH-DSS-DES-CBC3-SHA tls-ref-097.lan.cryptocom.ru:4401
+}      
diff --git a/tcl_tests/098.ciphers b/tcl_tests/098.ciphers
new file mode 100644 (file)
index 0000000..cbe8cf0
--- /dev/null
@@ -0,0 +1,11 @@
+rsa:1024 {
+       DHE-RSA-AES256-SHA      tls-ref-098.lan.cryptocom.ru:443
+       SSLv2:DES-CBC3-MD5 tls-ref-098.lan.cryptocom.ru:4402
+       SSLv3:DES-CBC-SHA tls-ref-098.lan.cryptocom.ru:4403
+       RC4-SHA tls-ref-098.lan.cryptocom.ru:4404
+}
+
+dsa:dsaparams.pem {
+       DHE-DSS-AES256-SHA  tls-ref-098.lan.cryptocom.ru:444
+       SSLv3:EDH-DSS-DES-CBC3-SHA tls-ref-098.lan.cryptocom.ru:4401
+}      
diff --git a/tcl_tests/_exists b/tcl_tests/_exists
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tcl_tests/aes0.enc b/tcl_tests/aes0.enc
new file mode 100644 (file)
index 0000000..372afb6
Binary files /dev/null and b/tcl_tests/aes0.enc differ
diff --git a/tcl_tests/aes1.enc b/tcl_tests/aes1.enc
new file mode 100644 (file)
index 0000000..b9e00dc
Binary files /dev/null and b/tcl_tests/aes1.enc differ
diff --git a/tcl_tests/apache.try b/tcl_tests/apache.try
new file mode 100644 (file)
index 0000000..b126970
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/tclsh
+lappend auto_path [file dirname [info script]] 
+package require ossltest
+
+set test_dir [file normalize [file dirname [info script]]]
+
+cd $::test::dir
+start_tests "Тесты на API, используемый только в Apache"
+
+
+
+makeCA
+
+if {$tcl_platform(platform) eq "windows"} { 
+  # Add openssl dir to PATH
+  set dlldir [file nativename [file normalize $test_dir/../../openssl]]
+  set env(PATH) "$dlldir;$env(PATH)"
+}
+test "EVP_PKEY_copy_parameters gost94" {
+       makeRegisteredUser "U_apache_94" gost94:A
+       exec $test_dir/copy_param U_apache_94/seckey.pem U_apache_94/cert.pem
+} 0 "EVP_PKEY_missing_parameters before copy: 1
+EVP_PKEY_missing_parameters after copy: 0
+Check private key:Ok"  
+
+test "EVP_PKEY_copy_parameters gost2001" {
+       makeRegisteredUser "U_apache_94" gost2001:A
+       exec $test_dir/copy_param U_apache_94/seckey.pem U_apache_94/cert.pem
+} 0 "EVP_PKEY_missing_parameters before copy: 1
+EVP_PKEY_missing_parameters after copy: 0
+Check private key:Ok"  
+
+end_tests
diff --git a/tcl_tests/asn.tcl b/tcl_tests/asn.tcl
new file mode 100644 (file)
index 0000000..d9a2581
--- /dev/null
@@ -0,0 +1,1419 @@
+#-----------------------------------------------------------------------------
+#   Copyright (C) 1999-2004 Jochen C. Loewer (loewerj@web.de)
+#   Copyright (C) 2004-2006 Michael Schlenker (mic42@users.sourceforge.net)
+#-----------------------------------------------------------------------------
+#   
+#   A partial ASN decoder/encoder implementation in plain Tcl. 
+#
+#   See ASN.1 (X.680) and BER (X.690).
+#   See 'asn_ber_intro.txt' in this directory.
+#
+#   This software is copyrighted by Jochen C. Loewer (loewerj@web.de). The 
+#   following terms apply to all files associated with the software unless 
+#   explicitly disclaimed in individual files.
+#
+#   The authors hereby grant permission to use, copy, modify, distribute,
+#   and license this software and its documentation for any purpose, provided
+#   that existing copyright notices are retained in all copies and that this
+#   notice is included verbatim in any distributions. No written agreement,
+#   license, or royalty fee is required for any of the authorized uses.
+#   Modifications to this software may be copyrighted by their authors
+#   and need not follow the licensing terms described here, provided that
+#   the new terms are clearly indicated on the first page of each file where
+#   they apply.
+#  
+#   IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+#   FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+#   ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+#   DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+#   POSSIBILITY OF SUCH DAMAGE.
+#
+#   THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+#   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+#   FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
+#   IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+#   NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+#   MODIFICATIONS.
+#
+#   written by Jochen Loewer
+#   3 June, 1999
+#
+#   $Id: asn.tcl,v 1.1 2012-04-04 10:50:38 igus Exp $
+#
+#-----------------------------------------------------------------------------
+
+# needed for using wide()
+package require Tcl 8.4
+
+namespace eval asn {
+    # Encoder commands
+    namespace export \
+        asnSequence \
+       asnSequenceFromList \
+        asnSet \
+       asnSetFromList \
+        asnApplicationConstr \
+        asnApplication \
+       asnContext\
+       asnContextConstr\
+        asnChoice \
+        asnChoiceConstr \
+        asnInteger \
+        asnEnumeration \
+        asnBoolean \
+        asnOctetString \
+        asnUTCTime \
+       asnNumericString \
+        asnPrintableString \
+        asnIA5String\
+       asnBMPString\
+       asnUTF8String\
+        asnBitString \
+        asnObjectIdentifer 
+        
+    # Decoder commands
+    namespace export \
+        asnGetResponse \
+        asnGetInteger \
+        asnGetEnumeration \
+        asnGetOctetString \
+        asnGetSequence \
+        asnGetSet \
+        asnGetApplication \
+       asnGetNumericString \
+        asnGetPrintableString \
+        asnGetIA5String \
+       asnGetBMPString \
+       asnGetUTF8String \
+        asnGetObjectIdentifier \
+        asnGetBoolean \
+        asnGetUTCTime \
+        asnGetBitString \
+        asnGetContext 
+    
+    # general BER utility commands    
+    namespace export \
+        asnPeekByte  \
+        asnGetLength \
+        asnRetag         
+        
+}
+
+#-----------------------------------------------------------------------------
+# Implementation notes:
+#
+# See the 'asn_ber_intro.txt' in this directory for an introduction
+# into BER/DER encoding of ASN.1 information. Bibliography information
+#
+#   A Layman's Guide to a Subset of ASN.1, BER, and DER
+#
+#   An RSA Laboratories Technical Note
+#   Burton S. Kaliski Jr.
+#   Revised November 1, 1993
+#
+#   Supersedes June 3, 1991 version, which was also published as
+#   NIST/OSI Implementors' Workshop document SEC-SIG-91-17.
+#   PKCS documents are available by electronic mail to
+#   <pkcs@rsa.com>.
+#
+#   Copyright (C) 1991-1993 RSA Laboratories, a division of RSA
+#   Data Security, Inc. License to copy this document is granted
+#   provided that it is identified as "RSA Data Security, Inc.
+#   Public-Key Cryptography Standards (PKCS)" in all material
+#   mentioning or referencing this document.
+#   003-903015-110-000-000
+#
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# asnLength : Encode some length data. Helper command.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnLength {len} {
+    
+    if {$len < 0} {
+        return -code error "Negative length octet requested"
+    }
+    if {$len < 128} {
+        # short form: ISO X.690 8.1.3.4 
+        return [binary format c $len]
+    }
+    # long form: ISO X.690 8.1.3.5
+    # try to use a minimal encoding, 
+    # even if not required by BER, but it is required by DER
+    # take care for signed vs. unsigned issues
+    if {$len < 256  } {
+        return [binary format H2c 81 [expr {$len - 256}]]
+    }
+    if {$len < 32769} {
+        # two octet signed value
+        return [binary format H2S 82 $len]
+    }
+    if {$len < 65536} {
+        return [binary format H2S 82 [expr {$len - 65536}]]
+    }
+    if {$len < 8388608} {
+        # three octet signed value    
+        return [binary format H2cS 83 [expr {$len >> 16}] [expr {($len & 0xFFFF) - 65536}]] 
+    }    
+    if {$len < 16777216} {
+        # three octet signed value    
+        return [binary format H2cS 83 [expr {($len >> 16) -256}] [expr {($len & 0xFFFF) -65536}]] 
+    }
+    if {$len < 2147483649} { 
+        # four octet signed value
+        return [binary format H2I 84 $len]
+    }
+    if {$len < 4294967296} {
+        # four octet unsigned value
+        return [binary format H2I 84 [expr {$len - 4294967296}]]
+    }
+    if {$len < 1099511627776} {
+        # five octet unsigned value
+        return [binary format H2 85][string range [binary format W $len] 3 end]  
+    }
+    if {$len < 281474976710656} {
+        # six octet unsigned value
+        return [binary format H2 86][string range [binary format W $len] 2 end]
+    }
+    if {$len < 72057594037927936} {
+        # seven octet value
+        return [binary format H2 87][string range [binary format W $len] 1 end]
+    }
+    
+    # must be a 64-bit wide signed value
+    return [binary format H2W 88 $len] 
+}
+
+#-----------------------------------------------------------------------------
+# asnSequence : Assumes that the arguments are already ASN encoded.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnSequence {args} {
+    asnSequenceFromList $args
+}
+
+proc ::asn::asnSequenceFromList {lst} {
+    # The sequence tag is 0x30. The length is arbitrary and thus full
+    # length coding is required. The arguments have to be BER encoded
+    # already. Constructed value, definite-length encoding.
+
+    set out ""
+    foreach part $lst {
+        append out $part
+    }
+    set len [string length $out]
+    return [binary format H2a*a$len 30 [asnLength $len] $out]
+}
+
+
+#-----------------------------------------------------------------------------
+# asnSet : Assumes that the arguments are already ASN encoded.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnSet {args} {
+    asnSetFromList $args
+}
+
+proc ::asn::asnSetFromList {lst} {
+    # The set tag is 0x31. The length is arbitrary and thus full
+    # length coding is required. The arguments have to be BER encoded
+    # already.
+
+    set out ""
+    foreach part $lst {
+        append out $part
+    }
+    set len [string length $out]
+    return [binary format H2a*a$len 31 [asnLength $len] $out]
+}
+
+
+#-----------------------------------------------------------------------------
+# asnApplicationConstr
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnApplicationConstr {appNumber args} {
+    # Packs the arguments into a constructed value with application tag.
+
+    set out ""
+    foreach part $args {
+        append out $part
+    }
+    set code [expr {0x060 + $appNumber}]
+    set len  [string length $out]
+    return [binary format ca*a$len $code [asnLength $len] $out]
+}
+
+#-----------------------------------------------------------------------------
+# asnApplication
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnApplication {appNumber data} {
+    # Packs the arguments into a constructed value with application tag.
+
+    set code [expr {0x040 + $appNumber}]
+    set len  [string length $data]
+    return [binary format ca*a$len $code [asnLength $len] $data]
+}
+
+#-----------------------------------------------------------------------------
+# asnContextConstr
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnContextConstr {contextNumber args} {
+    # Packs the arguments into a constructed value with application tag.
+
+    set out ""
+    foreach part $args {
+        append out $part
+    }
+    set code [expr {0x0A0 + $contextNumber}]
+    set len  [string length $out]
+    return [binary format ca*a$len $code [asnLength $len] $out]
+}
+
+#-----------------------------------------------------------------------------
+# asnContext
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnContext {contextNumber data} {
+    # Packs the arguments into a constructed value with application tag.
+    set code [expr {0x080 + $contextNumber}]
+    set len  [string length $data]
+    return [binary format ca*a$len $code [asnLength $len] $data]
+}
+#-----------------------------------------------------------------------------
+# asnChoice
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnChoice {appNumber args} {
+    # Packs the arguments into a choice construction.
+
+    set out ""
+    foreach part $args {
+        append out $part
+    }
+    set code [expr {0x080 + $appNumber}]
+    set len  [string length $out]
+    return [binary format ca*a$len $code [asnLength $len] $out]
+}
+
+#-----------------------------------------------------------------------------
+# asnChoiceConstr
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnChoiceConstr {appNumber args} {
+    # Packs the arguments into a choice construction.
+
+    set out ""
+    foreach part $args {
+        append out $part
+    }
+    set code [expr {0x0A0 + $appNumber}]
+    set len  [string length $out]
+    return [binary format ca*a$len $code [asnLength $len] $out]
+}
+
+#-----------------------------------------------------------------------------
+# asnInteger : Encode integer value.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnInteger {number} {
+    asnIntegerOrEnum 02 $number
+}
+
+#-----------------------------------------------------------------------------
+# asnEnumeration : Encode enumeration value.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnEnumeration {number} {
+    asnIntegerOrEnum 0a $number
+}
+
+#-----------------------------------------------------------------------------
+# asnIntegerOrEnum : Common code for Integers and Enumerations
+#                    No Bignum version, as we do not expect large Enums.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnIntegerOrEnum {tag number} {
+    # The integer tag is 0x02 , the Enum Tag 0x0a otherwise identical. 
+    # The length is 1, 2, 3, or 4, coded in a
+    # single byte. This can be done directly, no need to go through
+    # asnLength. The value itself is written in big-endian.
+
+    # Known bug/issue: The command cannot handle very wide integers, i.e.
+    # anything above 8 bytes length. Use asnBignumInteger for those.
+    
+    # check if we really have an int
+    set num $number
+    incr num
+    
+    if {($number >= -128) && ($number < 128)} {
+        return [binary format H2H2c $tag 01 $number]
+    }
+    if {($number >= -32768) && ($number < 32768)} {
+        return [binary format H2H2S $tag 02 $number]
+    }
+    if {($number >= -8388608) && ($number < 8388608)} {
+        set numberb [expr {$number & 0xFFFF}]
+        set numbera [expr {($number >> 16) & 0xFF}]
+        return [binary format H2H2cS $tag 03 $numbera $numberb]
+    }
+    if {($number >= -2147483648) && ($number < 2147483648)} {
+        return [binary format H2H2I $tag 04 $number]
+    }
+    if {($number >= -549755813888) && ($number < 549755813888)} {
+        set numberb [expr {$number & 0xFFFFFFFF}]
+        set numbera [expr {($number >> 32) & 0xFF}]
+        return [binary format H2H2cI $tag 05 $numbera $numberb]
+    }
+    if {($number >= -140737488355328) && ($number < 140737488355328)} {
+        set numberb [expr {$number & 0xFFFFFFFF}]
+        set numbera [expr {($number >> 32) & 0xFFFF}]
+        return [binary format H2H2SI $tag 06 $numbera $numberb]        
+    }
+    if {($number >= -36028797018963968) && ($number < 36028797018963968)} {
+        set numberc [expr {$number & 0xFFFFFFFF}]
+        set numberb [expr {($number >> 32) & 0xFFFF}]
+        set numbera [expr {($number >> 48) & 0xFF}]
+        return [binary format H2H2cSI $tag 07 $numbera $numberb $numberc]        
+    }    
+    if {($number >= -9223372036854775808) && ($number <= 9223372036854775807)} {
+        return [binary format H2H2W $tag 08 $number]
+    }
+    return -code error "Integer value to large to encode, use asnBigInteger" 
+}
+
+#-----------------------------------------------------------------------------
+# asnBigInteger : Encode a long integer value using math::bignum
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnBigInteger {bignum} {
+    # require math::bignum only if it is used
+    package require math::bignum
+    
+    # this is a hack to check for bignum...
+    if {[llength $bignum] < 2 || ([lindex $bignum 0] ne "bignum")} {
+        return -code error "expected math::bignum value got \"$bignum\""
+    }
+    if {[math::bignum::sign $bignum]} {
+        # generate two's complement form
+        set bits [math::bignum::bits $bignum]
+        set padding [expr {$bits % 8}]
+        set len [expr {int(ceil($bits / 8.0))}]
+        if {$padding == 0} {
+            # we need a complete extra byte for the sign
+            # unless this is a base 2 multiple
+            set test [math::bignum::fromstr 0]
+            math::bignum::setbit test [expr {$bits-1}]
+            if {[math::bignum::ne [math::bignum::abs $bignum] $test]} {
+                incr len
+            }
+        }
+        set exp [math::bignum::pow \
+                   [math::bignum::fromstr 256] \
+                   [math::bignum::fromstr $len]]
+        set bignum [math::bignum::add $bignum $exp]
+        set hex [math::bignum::tostr $bignum 16]
+    } else {
+        set bits [math::bignum::bits $bignum]
+        if {($bits % 8) == 0 && $bits > 0} {
+            set pad "00"
+        } else {
+            set pad ""
+        }
+        set hex $pad[math::bignum::tostr $bignum 16]
+    }
+    if {[string length $hex]%2} {
+        set hex "0$hex"
+    }
+    set octets [expr {(([string length $hex]+1)/2)}]
+    return [binary format H2a*H* 02 [asnLength $octets] $hex]   
+}
+
+
+#-----------------------------------------------------------------------------
+# asnBoolean : Encode a boolean value.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnBoolean {bool} {
+    # The boolean tag is 0x01. The length is always 1, coded in
+    # a single byte. This can be done directly, no need to go through
+    # asnLength. The value itself is written in big-endian.
+
+    return [binary format H2H2c 01 01 [expr {$bool ? 0x0FF : 0x0}]]
+}
+
+#-----------------------------------------------------------------------------
+# asnOctetString : Encode a string of arbitrary bytes
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnOctetString {string} {
+    # The octet tag is 0x04. The length is arbitrary, so we need
+    # 'asnLength' for full coding of the length.
+
+    set len [string length $string]
+    return [binary format H2a*a$len 04 [asnLength $len] $string]
+}
+
+#-----------------------------------------------------------------------------
+# asnNull : Encode a null value
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnNull {} {
+    # Null has only one valid encoding
+    return \x05\x00
+}
+
+#-----------------------------------------------------------------------------
+# asnBitstring : Encode a Bit String value
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnBitString {bitstring} {
+    # The bit string tag is 0x03.
+    # Bit strings can be either simple or constructed
+    # we always use simple encoding
+    
+    set bitlen [string length $bitstring]
+    set padding [expr {(8 - ($bitlen % 8)) % 8}]
+    set len [expr {($bitlen / 8) + 1}]
+    if {$padding != 0} {incr len}
+    
+    return [binary format H2a*B* 03 [asnLength $len] $bitstring]    
+}
+
+#-----------------------------------------------------------------------------
+# asnUTCTime : Encode an UTC time string
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnUTCTime {UTCtimestring} {
+    # the utc time tag is 0x17.
+    # 
+    # BUG: we do not check the string for well formedness
+    
+    set ascii [encoding convertto ascii $UTCtimestring]
+    set len [string length $ascii]
+    return [binary format H2a*a* 17 [asnLength $len] $ascii]
+}
+
+#-----------------------------------------------------------------------------
+# asnPrintableString : Encode a printable string
+#-----------------------------------------------------------------------------
+namespace eval asn {
+    variable nonPrintableChars {[^ A-Za-z0-9'()+,.:/?=-]}
+}      
+proc ::asn::asnPrintableString {string} {
+    # the printable string tag is 0x13
+    variable nonPrintableChars
+    # it is basically a restricted ascii string
+    if {[regexp $nonPrintableChars $string ]} {
+        return -code error "Illegal character in PrintableString."
+    }
+    
+    # check characters
+    set ascii [encoding convertto ascii $string]
+    return [asnEncodeString 13 $ascii]
+}
+
+#-----------------------------------------------------------------------------
+# asnIA5String : Encode an Ascii String
+#-----------------------------------------------------------------------------
+proc ::asn::asnIA5String {string} {
+    # the IA5 string tag is 0x16
+    # check for extended charachers
+    if {[string length $string]!=[string bytelength $string]} {
+       return -code error "Illegal character in IA5String"
+    }
+    set ascii [encoding convertto ascii $string]
+    return [asnEncodeString 16 $ascii]
+}
+
+#-----------------------------------------------------------------------------
+# asnNumericString : Encode a Numeric String type
+#-----------------------------------------------------------------------------
+namespace eval asn {
+    variable nonNumericChars {[^0-9 ]}
+}
+proc ::asn::asnNumericString {string} {
+    # the Numeric String type has tag 0x12
+    variable nonNumericChars
+    if {[regexp $nonNumericChars $string]} {
+        return -code error "Illegal character in Numeric String."
+    }
+    
+    return [asnEncodeString 12 $string]
+}
+#----------------------------------------------------------------------
+# asnBMPString: Encode a Tcl string as Basic Multinligval (UCS2) string
+#-----------------------------------------------------------------------
+proc asn::asnBMPString  {string} {
+    if {$::tcl_platform(byteOrder) eq "littleEndian"} {
+       set bytes ""
+       foreach {lo hi} [split [encoding convertto unicode $string] ""] {
+           append bytes $hi $lo
+       }       
+    } else {
+       set bytes [encoding convertto unicode $string]
+    }
+    return [asnEncodeString 1e $bytes]
+}      
+#---------------------------------------------------------------------------
+# asnUTF8String: encode tcl string as UTF8 String
+#----------------------------------------------------------------------------
+proc asn::asnUTF8String {string} {
+    return [asnEncodeString 0c [encoding convertto utf-8 $string]]
+}
+#-----------------------------------------------------------------------------
+# asnEncodeString : Encode an RestrictedCharacter String
+#-----------------------------------------------------------------------------
+proc ::asn::asnEncodeString {tag string} {
+    set len [string length $string]
+    return [binary format H2a*a$len $tag [asnLength $len] $string]    
+}
+
+#-----------------------------------------------------------------------------
+# asnObjectIdentifier : Encode an Object Identifier value
+#-----------------------------------------------------------------------------
+proc ::asn::asnObjectIdentifier {oid} {
+    # the object identifier tag is 0x06
+    
+    if {[llength $oid] < 2} {
+        return -code error "OID must have at least two subidentifiers."
+    }
+    
+    # basic check that it is valid
+    foreach identifier $oid {
+        if {$identifier < 0} {
+            return -code error \
+               "Malformed OID. Identifiers must be positive Integers."
+        }
+    }
+    
+    if {[lindex $oid 0] > 2} {
+            return -code error "First subidentifier must be 0,1 or 2"
+    }
+    if {[lindex $oid 1] > 39} {
+            return -code error \
+               "Second subidentifier must be between 0 and 39"
+    }
+    
+    # handle the special cases directly
+    switch [llength $oid] {
+        2  {  return [binary format H2H2c 06 01 \
+               [expr {[lindex $oid 0]*40+[lindex $oid 1]}]] }
+        default {
+              # This can probably be written much shorter. 
+              # Just a first try that works...
+              #
+              set octets [binary format c \
+               [expr {[lindex $oid 0]*40+[lindex $oid 1]}]]
+              foreach identifier [lrange $oid 2 end] {
+                  set d 128
+                  if {$identifier < 128} {
+                    set subidentifier [list $identifier]
+                  } else {  
+                    set subidentifier [list]
+                    # find the largest divisor
+                    
+                    while {($identifier / $d) >= 128} { 
+                       set d [expr {$d * 128}] 
+                   }
+                    # and construct the subidentifiers
+                    set remainder $identifier
+                    while {$d >= 128} {
+                        set coefficient [expr {($remainder / $d) | 0x80}]
+                        set remainder [expr {$remainder % $d}]
+                        set d [expr {$d / 128}]
+                        lappend subidentifier $coefficient
+                    }
+                    lappend subidentifier $remainder
+                  }
+                  append octets [binary format c* $subidentifier]
+              }
+              return [binary format H2a*a* 06 \
+                     [asnLength [string length $octets]] $octets]
+        }
+    }
+
+}
+
+#-----------------------------------------------------------------------------
+# asnGetResponse : Read a ASN response from a channel.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetResponse {sock data_var} {
+    upvar $data_var data
+
+    # We expect a sequence here (tag 0x30). The code below is an
+    # inlined replica of 'asnGetSequence', modified for reading from a
+    # channel instead of a string.
+
+    set tag [read $sock 1]
+
+    if {$tag == "\x30"} {
+    # The following code is a replica of 'asnGetLength', modified
+    # for reading the bytes from the channel instead of a string.
+
+        set len1 [read $sock 1]
+        binary scan $len1 c num
+        set length [expr {($num + 0x100) % 0x100}]
+
+        if {$length  >= 0x080} {
+        # The byte the read is not the length, but a prefix, and
+        # the lower nibble tells us how many bytes follow.
+
+            set len_length  [expr {$length & 0x7f}]
+
+        # BUG: We should not perform the value extraction for an
+        # BUG: improper length. It wastes cycles, and here it can
+        # BUG: cause us trouble, reading more data than there is
+        # BUG: on the channel. Depending on the channel
+        # BUG: configuration an attacker can induce us to block,
+        # BUG: causing a denial of service.
+            set lengthBytes [read $sock $len_length]
+
+            switch $len_length {
+                1 {
+            binary scan $lengthBytes     c length 
+            set length [expr {($length + 0x100) % 0x100}]
+                }
+                2 { binary scan $lengthBytes     S length }
+                3 { binary scan \x00$lengthBytes I length }
+                4 { binary scan $lengthBytes     I length }
+                default {
+                    return -code error \
+                       "length information too long ($len_length)"
+                }
+            }
+        }
+
+    # Now that the length is known we get the remainder,
+    # i.e. payload, and construct proper in-memory BER encoded
+    # sequence.
+
+        set rest [read $sock $length]
+        set data [binary format aa*a$length $tag [asnLength $length] $rest]
+    }  else {
+    # Generate an error message if the data is not a sequence as
+    # we expected.
+
+        set tag_hex ""
+        binary scan $tag H2 tag_hex
+        return -code error "unknown start tag [string length $tag] $tag_hex"
+    }
+}
+
+#-----------------------------------------------------------------------------
+# asnGetByte : Retrieve a single byte from the data (unsigned)
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetByte {data_var byte_var} {
+    upvar $data_var data $byte_var byte
+    
+    binary scan [string index $data 0] c byte
+    set byte [expr {($byte + 0x100) % 0x100}]  
+    set data [string range $data 1 end]
+
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnPeekByte : Retrieve a single byte from the data (unsigned) 
+#               without removing it.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnPeekByte {data_var byte_var} {
+    upvar $data_var data $byte_var byte
+    
+    binary scan [string index $data 0] c byte
+    set byte [expr {($byte + 0x100) % 0x100}]  
+
+    return
+}
+
+#-----------------------------------------------------------------------------
+# ansRetag: Remove an explicit tag with the real newTag
+#
+#-----------------------------------------------------------------------------
+proc ::asn::asnRetag {data_var newTag} {
+    upvar 1 $data_var data  
+    asnGetByte data tag
+    set data [binary format c $newTag]$data
+}
+
+#-----------------------------------------------------------------------------
+# asnGetBytes : Retrieve a block of 'length' bytes from the data.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetBytes {data_var length bytes_var} {
+    upvar $data_var data  $bytes_var bytes
+
+    incr length -1
+    set bytes [string range $data 0 $length]
+    incr length
+    set data [string range $data $length end]
+
+    return
+}
+
+
+#-----------------------------------------------------------------------------
+# asnGetLength : Decode an ASN length value (See notes)
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetLength {data_var length_var} {
+    upvar $data_var data  $length_var length
+
+    asnGetByte data length
+    if {$length == 0x080} {
+        return -code error "Indefinite length BER encoding not yet supported"
+    }
+    if {$length > 0x080} {
+    # The retrieved byte is a prefix value, and the integer in the
+    # lower nibble tells us how many bytes were used to encode the
+    # length data following immediately after this prefix.
+
+        set len_length [expr {$length & 0x7f}]
+        
+        if {[string length $data] < $len_length} {
+            return -code error \
+               "length information invalid, not enough octets left" 
+        }
+        
+        asnGetBytes data $len_length lengthBytes
+
+        switch $len_length {
+            1 {
+        # Efficiently coded data will not go through this
+        # path, as small length values can be coded directly,
+        # without a prefix.
+
+            binary scan $lengthBytes     c length 
+            set length [expr {($length + 0x100) % 0x100}]
+            }
+            2 { binary scan $lengthBytes     S length 
+            set length [expr {($length + 0x10000) % 0x10000}]
+            }
+            3 { binary scan \x00$lengthBytes I length 
+            set length [expr {($length + 0x1000000) % 0x1000000}]
+            }
+            4 { binary scan $lengthBytes     I length 
+            set length [expr {(wide($length) + 0x100000000) % 0x100000000}]
+            }
+            default {                
+                binary scan $lengthBytes H* hexstr
+                # skip leading zeros which are allowed by BER
+                set hexlen [string trimleft $hexstr 0] 
+                # check if it fits into a 64-bit signed integer
+                if {[string length $hexlen] > 16} {
+                    return -code error -errorcode {ARITH IOVERFLOW 
+                            {Length value too large for normal use, try asnGetBigLength}} \
+                           "Length value to large"
+                } elseif {  [string length $hexlen] == 16 \
+                       && ([string index $hexlen 0] & 0x8)} { 
+                    # check most significant bit, if set we need bignum
+                    return -code error -errorcode {ARITH IOVERFLOW 
+                            {Length value too large for normal use, try asnGetBigLength}} \
+                           "Length value to large"
+                } else {
+                    scan $hexstr "%lx" length
+                }
+            }
+        }
+    }
+    return
+}
+
+
+#-----------------------------------------------------------------------------
+# asnGetBigLength : Retrieve a length that can not be represented in 63-bit
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetBigLength {data_var biglength_var} {
+
+    # Does any real world code really need this? 
+    # If we encounter this, we are doomed to fail anyway, 
+    # (there would be an Exabyte inside the data_var, )
+    #
+    # So i implement it just for completness.
+    # 
+    package require math::bignum
+    
+    upvar $data_var data  $length_var length
+
+    asnGetByte data length
+    if {$length == 0x080} {
+        return -code error "Indefinite length BER encoding not yet supported"
+    }
+    if {$length > 0x080} {
+    # The retrieved byte is a prefix value, and the integer in the
+    # lower nibble tells us how many bytes were used to encode the
+    # length data following immediately after this prefix.
+
+        set len_length [expr {$length & 0x7f}]
+        
+        if {[string length $data] < $len_length} {
+            return -code error \
+               "length information invalid, not enough octets left" 
+        }
+        
+        asnGetBytes data $len_length lengthBytes
+        binary scan $lengthBytes H* hexlen
+        set length [math::bignum::fromstr $hexlen 16]
+    }
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetInteger : Retrieve integer.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetInteger {data_var int_var} {
+    # Tag is 0x02. 
+
+    upvar $data_var data $int_var int
+
+    asnGetByte   data tag
+
+    if {$tag != 0x02} {
+        return -code error \
+            [format "Expected Integer (0x02), but got %02x" $tag]
+    }
+
+    asnGetLength data len
+    asnGetBytes  data $len integerBytes
+
+    set int ?
+
+    switch $len {
+        1 { binary scan $integerBytes     c int }
+        2 { binary scan $integerBytes     S int }
+        3 { 
+            # check for negative int and pad 
+            scan [string index $integerBytes 0] %c byte
+            if {$byte & 128} {
+                binary scan \xff$integerBytes I int
+            } else {
+                binary scan \x00$integerBytes I int 
+            }
+          }
+        4 { binary scan $integerBytes     I int }
+        5 -
+        6 -
+        7 -
+        8 {
+            # check for negative int and pad
+            scan [string index $integerBytes 0] %c byte
+            if {$byte & 128} {
+                set pad [string repeat \xff [expr {8-$len}]]
+            } else {
+                set pad [string repeat \x00 [expr {8-$len}]]
+            }
+            binary scan $pad$integerBytes W int 
+        }
+        default {
+        # Too long, or prefix coding was used.
+            return -code error "length information too long"
+        }
+    }
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetBigInteger : Retrieve a big integer.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetBigInteger {data_var bignum_var} {
+    # require math::bignum only if it is used
+    package require math::bignum
+
+    # Tag is 0x02. We expect that the length of the integer is coded with
+    # maximal efficiency, i.e. without a prefix 0x81 prefix. If a prefix
+    # is used this decoder will fail.
+
+    upvar $data_var data $bignum_var bignum
+
+    asnGetByte   data tag
+
+    if {$tag != 0x02} {
+        return -code error \
+            [format "Expected Integer (0x02), but got %02x" $tag]
+    }
+
+    asnGetLength data len
+    asnGetBytes  data $len integerBytes
+    
+    binary scan $integerBytes H* hex
+    set bignum [math::bignum::fromstr $hex 16]
+    set bits [math::bignum::bits $bignum]
+    set exp [math::bignum::pow \
+               [math::bignum::fromstr 2] \
+               [math::bignum::fromstr $bits]]
+    set big [math::bignum::sub $bignum $exp]
+    set bignum $big
+    
+    return    
+}
+
+
+
+#-----------------------------------------------------------------------------
+# asnGetEnumeration : Retrieve an enumeration id
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetEnumeration {data_var enum_var} {
+    # This is like 'asnGetInteger', except for a different tag.
+
+    upvar $data_var data $enum_var enum
+
+    asnGetByte   data tag
+
+    if {$tag != 0x0a} {
+        return -code error \
+            [format "Expected Enumeration (0x0a), but got %02x" $tag]
+    }
+
+    asnGetLength data len
+    asnGetBytes  data $len integerBytes
+    set enum ?
+
+    switch $len {
+        1 { binary scan $integerBytes     c enum }
+        2 { binary scan $integerBytes     S enum }
+        3 { binary scan \x00$integerBytes I enum }
+        4 { binary scan $integerBytes     I enum }
+        default {
+            return -code error "length information too long"
+        }
+    }
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetOctetString : Retrieve arbitrary string.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetOctetString {data_var string_var} {
+    # Here we need the full decoder for length data.
+
+    upvar $data_var data $string_var string
+    
+    asnGetByte data tag
+    if {$tag != 0x04} { 
+        return -code error \
+            [format "Expected Octet String (0x04), but got %02x" $tag]
+    }
+    asnGetLength data length
+    asnGetBytes  data $length temp
+    set string $temp
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetSequence : Retrieve Sequence data for further decoding.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetSequence {data_var sequence_var} {
+    # Here we need the full decoder for length data.
+
+    upvar $data_var data $sequence_var sequence
+
+    asnGetByte data tag
+    if {$tag != 0x030} { 
+        return -code error \
+            [format "Expected Sequence (0x30), but got %02x" $tag]
+    }    
+    asnGetLength data length
+    asnGetBytes  data $length temp
+    set sequence $temp
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetSet : Retrieve Set data for further decoding.
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetSet {data_var set_var} {
+    # Here we need the full decoder for length data.
+
+    upvar $data_var data $set_var set
+
+    asnGetByte data tag
+    if {$tag != 0x031} { 
+        return -code error \
+            [format "Expected Set (0x31), but got %02x" $tag]
+    }    
+    asnGetLength data length
+    asnGetBytes  data $length temp
+    set set $temp
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetApplication
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetApplication {data_var appNumber_var {content_var {}} {constructed_var {}}} {
+    upvar $data_var data $appNumber_var appNumber
+
+    asnGetByte   data tag
+    asnGetLength data length
+
+    if {($tag & 0xC0) != 0x040} {
+        return -code error \
+            [format "Expected Application (0x60 or 0x40), but got %02x" $tag]
+    }    
+    set appNumber [expr {$tag & 0x1F}]
+       if {[string length $constructed_var]} {
+               upvar 1 $constructed_var constructed
+               set constructed [expr {$tag & 0x20}]
+       }
+       if {[string length $content_var]} {
+               upvar 1 $content_var content
+               asnGetBytes data $length content
+       }       
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetBoolean: decode a boolean value
+#-----------------------------------------------------------------------------
+
+proc asn::asnGetBoolean {data_var bool_var} {
+    upvar $data_var data $bool_var bool
+
+    asnGetByte data tag
+    if {$tag != 0x01} {
+        return -code error \
+            [format "Expected Boolean (0x01), but got %02x" $tag]
+    }
+
+    asnGetLength data length
+    asnGetByte data byte
+    set bool [expr {$byte == 0 ? 0 : 1}]    
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetUTCTime: Extract an UTC Time string from the data. Returns a string
+#                representing an UTC Time.
+#
+#-----------------------------------------------------------------------------
+
+proc asn::asnGetUTCTime {data_var utc_var} {
+    upvar $data_var data $utc_var utc
+
+    asnGetByte data tag
+    if {$tag != 0x17} {
+        return -code error \
+            [format "Expected UTCTime (0x17), but got %02x" $tag]
+    }
+
+    asnGetLength data length
+    asnGetBytes data $length bytes
+    
+    # this should be ascii, make it explicit
+    set bytes [encoding convertfrom ascii $bytes]
+    binary scan $bytes a* utc
+    
+    return
+}
+
+
+#-----------------------------------------------------------------------------
+# asnGetBitString: Extract a Bit String value (a string of 0/1s) from the
+#                  ASN.1 data.
+#
+#-----------------------------------------------------------------------------
+
+proc asn::asnGetBitString {data_var bitstring_var} {
+    upvar $data_var data $bitstring_var bitstring
+
+    asnGetByte data tag
+    if {$tag != 0x03} {
+        return -code error \
+            [format "Expected Bit String (0x03), but got %02x" $tag]
+    }
+    
+    asnGetLength data length
+    # get the number of padding bits used at the end
+    asnGetByte data padding
+    incr length -1
+    asnGetBytes data $length bytes
+    binary scan $bytes B* bits
+    
+    # cut off the padding bits
+    set bits [string range $bits 0 end-$padding]
+    set bitstring $bits
+}
+
+#-----------------------------------------------------------------------------
+# asnGetObjectIdentifier: Decode an ASN.1 Object Identifier (OID) into
+#                         a Tcl list of integers.
+#-----------------------------------------------------------------------------
+
+proc asn::asnGetObjectIdentifier {data_var oid_var} {
+      upvar $data_var data $oid_var oid
+
+      asnGetByte data tag
+      if {$tag != 0x06} {
+        return -code error \
+            [format "Expected Object Identifier (0x06), but got %02x" $tag]  
+      }
+      asnGetLength data length
+      
+      # the first byte encodes the OID parts in position 0 and 1
+      asnGetByte data val
+      set oid [expr {$val / 40}]
+      lappend oid [expr {$val % 40}]
+      incr length -1
+      
+      # the next bytes encode the remaining parts of the OID
+      set bytes [list]
+      set incomplete 0
+      while {$length} {
+        asnGetByte data octet
+        incr length -1
+        if {$octet < 128} {
+            set oidval $octet
+            set mult 128
+            foreach byte $bytes {
+                if {$byte != {}} {
+                incr oidval [expr {$mult*$byte}]    
+                set mult [expr {$mult*128}]
+                }
+            }
+            lappend oid $oidval
+            set bytes [list]
+            set incomplete 0
+        } else {
+            set byte [expr {$octet-128}]
+            set bytes [concat [list $byte] $bytes]
+            set incomplete 1
+        }                      
+      }
+      if {$incomplete} {
+        return -code error "OID Data is incomplete, not enough octets."
+      }
+      return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetContext: Decode an explicit context tag 
+#
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetContext {data_var contextNumber_var {content_var {}} {constructed_var {}}} {
+    upvar 1 $data_var data $contextNumber_var contextNumber
+
+    asnGetByte   data tag
+    asnGetLength data length
+
+    if {($tag & 0xC0) != 0x080} {
+        return -code error \
+            [format "Expected Context (0xa0 or 0x80), but got %02x" $tag]
+    }    
+    set contextNumber [expr {$tag & 0x1F}]
+       if {[string length $constructed_var]} {
+               upvar 1 $constructed_var constructed
+               set constructed [expr {$tag & 0x20}]
+       }
+       if {[string length $content_var]} {
+               upvar 1 $content_var content
+               asnGetBytes data $length content
+       }       
+    return
+}
+
+
+#-----------------------------------------------------------------------------
+# asnGetNumericString: Decode a Numeric String from the data
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetNumericString {data_var print_var} {
+    upvar 1 $data_var data $print_var print
+
+    asnGetByte data tag
+    if {$tag != 0x12} {
+        return -code error \
+            [format "Expected Numeric String (0x12), but got %02x" $tag]  
+    }
+    asnGetLength data length 
+    asnGetBytes data $length string
+    set print [encoding convertfrom ascii $string]
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetPrintableString: Decode a Printable String from the data
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetPrintableString {data_var print_var} {
+    upvar $data_var data $print_var print
+
+    asnGetByte data tag
+    if {$tag != 0x13} {
+        return -code error \
+            [format "Expected Printable String (0x13), but got %02x" $tag]  
+    }
+    asnGetLength data length 
+    asnGetBytes data $length string
+    set print [encoding convertfrom ascii $string]
+    return
+}
+
+#-----------------------------------------------------------------------------
+# asnGetIA5String: Decode a IA5(ASCII) String from the data
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetIA5String {data_var print_var} {
+    upvar $data_var data $print_var print
+
+    asnGetByte data tag
+    if {$tag != 0x16} {
+        return -code error \
+            [format "Expected IA5 String (0x16), but got %02x" $tag]  
+    }
+    asnGetLength data length 
+    asnGetBytes data $length string
+    set print [encoding convertfrom ascii $string]
+    return
+}
+#------------------------------------------------------------------------
+# asnGetBMPString: Decode Basic Multiningval (UCS2 string) from data
+#------------------------------------------------------------------------
+proc asn::asnGetBMPString {data_var print_var} {
+       upvar $data_var data $print_var print
+    asnGetByte data tag
+    if {$tag != 0x1e} {
+        return -code error \
+            [format "Expected BMP String (0x1e), but got %02x" $tag]  
+    }
+    asnGetLength data length 
+       asnGetBytes data $length string
+       if {$::tcl_platform(byteOrder) eq "littleEndian"} {
+               set str2 ""
+               foreach {hi lo} [split $string ""] {
+                       append str2 $lo $hi
+               }
+       } else {
+               set str2 $string
+       }
+       set print [encoding convertfrom unicode $str2]
+       return
+}      
+#------------------------------------------------------------------------
+# asnGetUTF8String: Decode UTF8 string from data
+#------------------------------------------------------------------------
+proc asn::asnGetUTF8String {data_var print_var} {
+       upvar $data_var data $print_var print
+    asnGetByte data tag
+    if {$tag != 0x0c} {
+        return -code error \
+            [format "Expected UTF8 String (0x0c), but got %02x" $tag]  
+    }
+    asnGetLength data length 
+       asnGetBytes data $length string
+       #there should be some error checking to see if input is
+       #properly-formatted utf8
+       set print [encoding convertfrom utf-8 $string]
+       
+       return
+}      
+#-----------------------------------------------------------------------------
+# asnGetNull: decode a NULL value
+#-----------------------------------------------------------------------------
+
+proc ::asn::asnGetNull {data_var} {
+    upvar $data_var data 
+
+    asnGetByte data tag
+    if {$tag != 0x05} {
+        return -code error \
+            [format "Expected NULL (0x05), but got %02x" $tag]
+    }
+
+    asnGetLength data length
+    asnGetBytes data $length bytes
+    
+    # we do not check the null data, all bytes must be 0x00
+    
+    return
+}
+
+#----------------------------------------------------------------------------
+# MultiType string routines
+#----------------------------------------------------------------------------
+
+namespace eval asn {
+       variable stringTypes
+       array set stringTypes {
+               12 NumericString 
+               13 PrintableString 
+               16 IA5String 
+               1e BMPString 
+               0c UTF8String 
+               14 T61String
+               15 VideotexString
+               1a VisibleString
+               1b GeneralString
+               1c UniversalString
+       }       
+       variable defaultStringType UTF8
+}      
+#---------------------------------------------------------------------------
+# asnGetString - get readable string automatically detecting its type
+#---------------------------------------------------------------------------
+proc ::asn::asnGetString {data_var print_var {type_var {}}} {
+       variable stringTypes
+       upvar $data_var data $print_var print
+       asnPeekByte data tag
+       set tag [format %02x $tag]
+       if {![info exists stringTypes($tag)]} {
+               return -code error "Expected one of string types, but got $tag"
+       }
+       asnGet$stringTypes($tag) data print
+       if {[string length $type_var]} {
+               upvar $type_var type
+               set type $stringTypes($tag)
+       }       
+}
+#---------------------------------------------------------------------
+# defaultStringType - set or query default type for unrestricted strings
+#---------------------------------------------------------------------
+proc ::asn::defaultStringType {{type {}}} {
+       variable defaultStringType
+       if {![string length $type]} {
+               return $defaultStringType
+       }
+       if {$type ne "BMP" && $type ne "UTF8"} {
+               return -code error "Invalid default string type. Should be one of BMP, UTF8"
+       }
+       set defaultStringType $type
+       return
+}      
+
+#---------------------------------------------------------------------------
+# asnString - encode readable string into most restricted type possible
+#---------------------------------------------------------------------------
+
+proc ::asn::asnString {string} {
+       variable nonPrintableChars
+       variable nonNumericChars
+       if {[string length $string]!=[string bytelength $string]} {
+       # There are non-ascii character
+               variable defaultStringType
+               return [asn${defaultStringType}String $string]
+       } elseif {![regexp $nonNumericChars $string]} {
+               return [asnNumericString $string]
+       } elseif {![regexp $nonPrintableChars $string]} {
+               return [asnPrintableString $string]
+       } else {
+               return [asnIA5String $string]
+       }       
+}
+
+#-----------------------------------------------------------------------------
+package provide asn 0.7.1
+
diff --git a/tcl_tests/base64.tcl b/tcl_tests/base64.tcl
new file mode 100644 (file)
index 0000000..21f1d43
--- /dev/null
@@ -0,0 +1,326 @@
+# base64.tcl --
+#
+# Encode/Decode base64 for a string
+# Stephen Uhler / Brent Welch (c) 1997 Sun Microsystems
+# The decoder was done for exmh by Chris Garrigues
+#
+# Copyright (c) 1998-2000 by Ajuba Solutions.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# RCS: @(#) $Id: base64.tcl,v 1.1 2012-04-04 10:50:38 igus Exp $
+
+# Version 1.0   implemented Base64_Encode, Base64_Decode
+# Version 2.0   uses the base64 namespace
+# Version 2.1   fixes various decode bugs and adds options to encode
+# Version 2.2   is much faster, Tcl8.0 compatible
+# Version 2.2.1 bugfixes
+# Version 2.2.2 bugfixes
+# Version 2.3   bugfixes and extended to support Trf
+
+# @mdgen EXCLUDE: base64c.tcl
+
+package require Tcl 8.2
+namespace eval ::base64 {
+    namespace export encode decode
+}
+
+if {![catch {package require Trf 2.0}]} {
+    # Trf is available, so implement the functionality provided here
+    # in terms of calls to Trf for speed.
+
+    # ::base64::encode --
+    #
+    #  Base64 encode a given string.
+    #
+    # Arguments:
+    #  args    ?-maxlen maxlen? ?-wrapchar wrapchar? string
+    #  
+    #          If maxlen is 0, the output is not wrapped.
+    #
+    # Results:
+    #  A Base64 encoded version of $string, wrapped at $maxlen characters
+    #  by $wrapchar.
+    
+    proc ::base64::encode {args} {
+       # Set the default wrapchar and maximum line length to match the output
+       # of GNU uuencode 4.2.  Various RFCs allow for different wrapping 
+       # characters and wraplengths, so these may be overridden by command line
+       # options.
+       set wrapchar "\n"
+       set maxlen 60
+
+       if { [llength $args] == 0 } {
+           error "wrong # args: should be \"[lindex [info level 0] 0]\
+                   ?-maxlen maxlen? ?-wrapchar wrapchar? string\""
+       }
+
+       set optionStrings [list "-maxlen" "-wrapchar"]
+       for {set i 0} {$i < [llength $args] - 1} {incr i} {
+           set arg [lindex $args $i]
+           set index [lsearch -glob $optionStrings "${arg}*"]
+           if { $index == -1 } {
+               error "unknown option \"$arg\": must be -maxlen or -wrapchar"
+           }
+           incr i
+           if { $i >= [llength $args] - 1 } {
+               error "value for \"$arg\" missing"
+           }
+           set val [lindex $args $i]
+
+           # The name of the variable to assign the value to is extracted
+           # from the list of known options, all of which have an
+           # associated variable of the same name as the option without
+           # a leading "-". The [string range] command is used to strip
+           # of the leading "-" from the name of the option.
+           #
+           # FRINK: nocheck
+           set [string range [lindex $optionStrings $index] 1 end] $val
+       }
+    
+       # [string is] requires Tcl8.2; this works with 8.0 too
+       if {[catch {expr {$maxlen % 2}}]} {
+           error "expected integer but got \"$maxlen\""
+       }
+
+       set string [lindex $args end]
+       set result [::base64 -mode encode -- $string]
+       set result [string map [list \n ""] $result]
+
+       if {$maxlen > 0} {
+           set res ""
+           set edge [expr {$maxlen - 1}]
+           while {[string length $result] > $maxlen} {
+               append res [string range $result 0 $edge]$wrapchar
+               set result [string range $result $maxlen end]
+           }
+           if {[string length $result] > 0} {
+               append res $result
+           }
+           set result $res
+       }
+
+       return $result
+    }
+
+    # ::base64::decode --
+    #
+    #  Base64 decode a given string.
+    #
+    # Arguments:
+    #  string  The string to decode.  Characters not in the base64
+    #          alphabet are ignored (e.g., newlines)
+    #
+    # Results:
+    #  The decoded value.
+
+    proc ::base64::decode {string} {
+       regsub -all {\s} $string {} string
+       ::base64 -mode decode -- $string
+    }
+
+} else {
+    # Without Trf use a pure tcl implementation
+
+    namespace eval base64 {
+       variable base64 {}
+       variable base64_en {}
+
+       # We create the auxiliary array base64_tmp, it will be unset later.
+
+       set i 0
+       foreach char {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
+               a b c d e f g h i j k l m n o p q r s t u v w x y z \
+               0 1 2 3 4 5 6 7 8 9 + /} {
+           set base64_tmp($char) $i
+           lappend base64_en $char
+           incr i
+       }
+
+       #
+       # Create base64 as list: to code for instance C<->3, specify
+       # that [lindex $base64 67] be 3 (C is 67 in ascii); non-coded
+       # ascii chars get a {}. we later use the fact that lindex on a
+       # non-existing index returns {}, and that [expr {} < 0] is true
+       #
+
+       # the last ascii char is 'z'
+       scan z %c len
+       for {set i 0} {$i <= $len} {incr i} {
+           set char [format %c $i]
+           set val {}
+           if {[info exists base64_tmp($char)]} {
+               set val $base64_tmp($char)
+           } else {
+               set val {}
+           }
+           lappend base64 $val
+       }
+
+       # code the character "=" as -1; used to signal end of message
+       scan = %c i
+       set base64 [lreplace $base64 $i $i -1]
+
+       # remove unneeded variables
+       unset base64_tmp i char len val
+
+       namespace export encode decode
+    }
+
+    # ::base64::encode --
+    #
+    #  Base64 encode a given string.
+    #
+    # Arguments:
+    #  args    ?-maxlen maxlen? ?-wrapchar wrapchar? string
+    #  
+    #          If maxlen is 0, the output is not wrapped.
+    #
+    # Results:
+    #  A Base64 encoded version of $string, wrapped at $maxlen characters
+    #  by $wrapchar.
+    
+    proc ::base64::encode {args} {
+       set base64_en $::base64::base64_en
+       
+       # Set the default wrapchar and maximum line length to match the output
+       # of GNU uuencode 4.2.  Various RFCs allow for different wrapping 
+       # characters and wraplengths, so these may be overridden by command line
+       # options.
+       set wrapchar "\n"
+       set maxlen 60
+
+       if { [llength $args] == 0 } {
+           error "wrong # args: should be \"[lindex [info level 0] 0]\
+                   ?-maxlen maxlen? ?-wrapchar wrapchar? string\""
+       }
+
+       set optionStrings [list "-maxlen" "-wrapchar"]
+       for {set i 0} {$i < [llength $args] - 1} {incr i} {
+           set arg [lindex $args $i]
+           set index [lsearch -glob $optionStrings "${arg}*"]
+           if { $index == -1 } {
+               error "unknown option \"$arg\": must be -maxlen or -wrapchar"
+           }
+           incr i
+           if { $i >= [llength $args] - 1 } {
+               error "value for \"$arg\" missing"
+           }
+           set val [lindex $args $i]
+
+           # The name of the variable to assign the value to is extracted
+           # from the list of known options, all of which have an
+           # associated variable of the same name as the option without
+           # a leading "-". The [string range] command is used to strip
+           # of the leading "-" from the name of the option.
+           #
+           # FRINK: nocheck
+           set [string range [lindex $optionStrings $index] 1 end] $val
+       }
+    
+       # [string is] requires Tcl8.2; this works with 8.0 too
+       if {[catch {expr {$maxlen % 2}}]} {
+           error "expected integer but got \"$maxlen\""
+       }
+
+       set string [lindex $args end]
+
+       set result {}
+       set state 0
+       set length 0
+
+
+       # Process the input bytes 3-by-3
+
+       binary scan $string c* X
+       foreach {x y z} $X {
+           # Do the line length check before appending so that we don't get an
+           # extra newline if the output is a multiple of $maxlen chars long.
+           if {$maxlen && $length >= $maxlen} {
+               append result $wrapchar
+               set length 0
+           }
+       
+           append result [lindex $base64_en [expr {($x >>2) & 0x3F}]] 
+           if {$y != {}} {
+               append result [lindex $base64_en [expr {(($x << 4) & 0x30) | (($y >> 4) & 0xF)}]] 
+               if {$z != {}} {
+                   append result \
+                           [lindex $base64_en [expr {(($y << 2) & 0x3C) | (($z >> 6) & 0x3)}]]
+                   append result [lindex $base64_en [expr {($z & 0x3F)}]]
+               } else {
+                   set state 2
+                   break
+               }
+           } else {
+               set state 1
+               break
+           }
+           incr length 4
+       }
+       if {$state == 1} {
+           append result [lindex $base64_en [expr {(($x << 4) & 0x30)}]]== 
+       } elseif {$state == 2} {
+           append result [lindex $base64_en [expr {(($y << 2) & 0x3C)}]]=  
+       }
+       return $result
+    }
+
+    # ::base64::decode --
+    #
+    #  Base64 decode a given string.
+    #
+    # Arguments:
+    #  string  The string to decode.  Characters not in the base64
+    #          alphabet are ignored (e.g., newlines)
+    #
+    # Results:
+    #  The decoded value.
+
+    proc ::base64::decode {string} {
+       if {[string length $string] == 0} {return ""}
+
+       set base64 $::base64::base64
+       set output "" ; # Fix for [Bug 821126]
+
+       binary scan $string c* X
+       foreach x $X {
+           set bits [lindex $base64 $x]
+           if {$bits >= 0} {
+               if {[llength [lappend nums $bits]] == 4} {
+                   foreach {v w z y} $nums break
+                   set a [expr {($v << 2) | ($w >> 4)}]
+                   set b [expr {(($w & 0xF) << 4) | ($z >> 2)}]
+                   set c [expr {(($z & 0x3) << 6) | $y}]
+                   append output [binary format ccc $a $b $c]
+                   set nums {}
+               }               
+           } elseif {$bits == -1} {
+               # = indicates end of data.  Output whatever chars are left.
+               # The encoding algorithm dictates that we can only have 1 or 2
+               # padding characters.  If x=={}, we have 12 bits of input 
+               # (enough for 1 8-bit output).  If x!={}, we have 18 bits of
+               # input (enough for 2 8-bit outputs).
+               
+               foreach {v w z} $nums break
+               set a [expr {($v << 2) | (($w & 0x30) >> 4)}]
+               if {$z == {}} {
+                   append output [binary format c $a ]
+               } else {
+                   set b [expr {(($w & 0xF) << 4) | (($z & 0x3C) >> 2)}]
+                   append output [binary format cc $a $b]
+               }               
+               break
+           } else {
+               # RFC 2045 says that line breaks and other characters not part
+               # of the Base64 alphabet must be ignored, and that the decoder
+               # can optionally emit a warning or reject the message.  We opt
+               # not to do so, but to just ignore the character. 
+               continue
+           }
+       }
+       return $output
+    }
+}
+
+package provide base64 2.3.2
diff --git a/tcl_tests/ca.try b/tcl_tests/ca.try
new file mode 100644 (file)
index 0000000..c84088c
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на команду ca" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_pair_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_pair_list {gost2001:A {gost2001:B} gost2012_256:A {gost2012_256:C} gost2012_512:B {gost2012_256:B gost2012_512:A}}}
+               "open" {set alg_pair_list {gost2001:A {gost2001:B} gost2012_256:A {gost2012_256:C} gost2012_512:B {gost2012_256:B gost2012_512:A}}}
+       }
+}
+
+foreach {ca_alg alg_list} $alg_pair_list {
+       set ca_alg_fn [string map {":" "_"} $ca_alg]
+
+test "Creating CA" { 
+       makeCA ${testname}CA-$ca_alg_fn $ca_alg
+} 0 1
+
+set serial_list ""
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set userdir U_ca_${alg_fn}_for_${ca_alg_fn}
+
+#Depends on previous
+test "Creating user request" {
+       makeUser $userdir $alg
+} 0 1
+
+test -skip {![file exists $userdir/req.pem]}  "Registering cert at CA" {
+       grep Sign [openssl "ca -config $::test::ca/ca.conf -in $userdir/req.pem -out $userdir/cert.pem -batch -notext"] 
+} 0 "Signature ok
+"
+if [file exists $userdir/req.pem] {
+set cert [getFile $userdir/req.pem]
+makeFile $userdir/broken.pem  [hackPem "Cryptocom" $cert "Kriptokom"]
+}
+test -skip {![file exists $userdir/broken.pem]} "Registering broken request at ca" {
+       grep Sign [openssl "ca -config $::test::ca/ca.conf -in $userdir/broken.pem -out $userdir/badcert.pem -batch"]
+} 0 "Signature did not match the certificate request
+"
+
+#test "Generating self-signed CA certificate" {
+#
+#} 0 "not written"
+
+test  "Revoking certificate" {
+       set revoking_cert $::test::ca/newcerts/[string trim [getFile $::test::ca/serial.old]].pem
+       append serial_list [regsub "serial=" [openssl "x509 -in $revoking_cert -noout -serial"] "    Serial Number: "]
+       grep "Data Base" [openssl "ca -crl_reason keyCompromize -crl_compromise [clock\
+       format [clock seconds]  -format %Y%m%d%H%M%SZ] -revoke $revoking_cert -config $::test::ca/ca.conf"]
+} 0 "Data Base Updated
+"
+test -createsfiles test.crl "Generating CRL" {
+       openssl "ca -gencrl -config $::test::ca/ca.conf -out test.crl"
+       file copy -force $::test::ca/cacert.pem test_crl_cacert.pem
+       file exist test.crl
+} 0 1  
+
+
+test -skip {![file exists test.crl]} "Displaying CRL" {
+       grep "(Serial|Version|Signature Alg|Issuer)" [openssl "crl -text -noout -in test.crl"]
+} 0 "        Version 2 (0x1)
+        Signature Algorithm: [hash_with_sign_long_name $ca_alg]
+        Issuer: C = RU, L = Moscow, CN = Test CA $ca_alg, O = Cryptocom, OU = OpenSSL CA, emailAddress = openssl@cryptocom.ru
+$serial_list    Signature Algorithm: [hash_with_sign_long_name  $ca_alg]
+"
+
+test -skip {![file exists test.crl]} "Verifying CRL OK" {
+       grep verify [openssl "crl -in test.crl -noout -CAfile $::test::ca/cacert.pem"]
+} 0 "verify OK
+"
+
+test -skip {![file exists test.crl]} "Verifying corrupted CRL" {
+       makeFile "badcrl.pem" [hackPem "\01\x1E" [getFile test.crl] "\01\0"]
+       grep verify [openssl "crl -in badcrl.pem -noout -CAfile $::test::ca/cacert.pem"]
+} 0 "verify failure
+"
+
+test "Verifying CA certificate" {
+       grep "(cacert.pem|error|OK)" [openssl "verify $::test::ca/cacert.pem"]
+} 1 "error $::test::ca/cacert.pem: verification failed
+STDERR CONTENTS:
+C = RU, L = Moscow, CN = Test CA $ca_alg, O = Cryptocom, OU = OpenSSL CA, emailAddress = openssl@cryptocom.ru
+error 18 at 0 depth lookup: self signed certificate"
+
+
+
+test "Verifying certificate" {
+       grep "cert.pem" [openssl "verify -CAfile $::test::ca/cacert.pem $userdir/cert.pem"]
+} 0 "$userdir/cert.pem: OK
+"
+
+test "Verifying bad certificate" {
+       makeFile "badcert.pem" [hackPem "Team" [getFile $userdir/cert.pem] "meat"]
+       openssl "verify -CAfile $::test::ca/cacert.pem badcert.pem"
+} 1 "certificate signature failure"
+
+test "Verifying revoked certificate" {
+       makeFile ca_crl.pem "[getFile $::test::ca/cacert.pem]\n[getFile test.crl]"
+       openssl "verify -crl_check -CAfile ca_crl.pem $userdir/cert.pem"
+} 1 "certificate revoked"
+
+test "Create a PKCS#7 structure from a certificate and CRL" {
+       openssl "crl2pkcs7 -in test.crl -certfile $userdir/cert.pem -out $userdir/p7.pem"
+       extract_oids $userdir/p7.pem PEM
+} 0 [mkObjList [hash_with_sign_long_name $ca_alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [hash_with_sign_long_name $ca_alg] [hash_with_sign_long_name $ca_alg] [hash_with_sign_long_name $ca_alg]]
+
+test "Creates a PKCS#7 structure without CRL" {
+       openssl "crl2pkcs7 -nocrl -certfile $userdir/cert.pem -certfile $::test::ca/cacert.pem -out $userdir/p7_nocrl.pem"
+       extract_oids $userdir/p7_nocrl.pem PEM
+} 0 [mkObjList [hash_with_sign_long_name $ca_alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]]  [hash_with_sign_long_name $ca_alg] [hash_with_sign_long_name $ca_alg] [alg_long_name $ca_alg] [pubkey_long_name $ca_alg] [param_hash_long_name [param_hash $ca_alg]] [hash_with_sign_long_name $ca_alg]]
+
+}
+
+}
+
+end_tests
diff --git a/tcl_tests/calchash.tcl b/tcl_tests/calchash.tcl
new file mode 100755 (executable)
index 0000000..ec68961
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require test
+
+if {$::tcl_platform(platform) eq "windows"} {
+       set prefix {//laputa/dist/magpro/FSB_CryptoPack_21.1/binaries}
+} else {
+       set prefix {/net/laputa/pub/magpro/FSB_CryptoPack_21.1/binaries}
+}
+set PREFIX_ENV_NAME CALCHASH_PREFIX
+if {$argc != 1} {
+        puts stderr "Usage $argv0 path"
+       puts stderr "This script tests programms prefix/path/calchach and prefix/path/gostsum."
+       puts stderr "Defauld prefix is $prefix"
+       puts stderr "Prefix can be changes by envirament veriable $PREFIX_ENV_NAME"
+        exit 1
+}
+
+if {[info exist env($PREFIX_ENV_NAME)]} {
+       set prefix $env($PREFIX_ENV_NAME)
+}
+set path [lindex $argv 0]
+
+set testdir [exec hostname]-hashes
+puts $testdir
+catch {file delete -force $testdir}
+file mkdir $testdir
+cd $testdir
+
+start_tests "Тесты для программ calchash и gostsum"
+
+test -createsfiles dgst.dat "calchash" {
+       makeFile dgst.dat [string repeat "Test data to digest.\n" 100] binary
+       string match *DB9232D96CAE7AABA817350EF6CF4C25604D8FD36965F78CEB3CE59FD31CCB2A [exec $prefix/$path/calchash dgst.dat]
+} 0 1 
+
+test -platform unix "gostsum (paramset cryptopro-A)" {
+       exec $prefix/$path/gostsum dgst.dat
+} 0 "5c8621c036f8636fa3ea711a78e5051f607c87b4b715482af74b2b1cce62e442 dgst.dat" 
+
+
+test -platform unix "gostsum -t (paramset test)" {
+       exec $prefix/$path/gostsum -t dgst.dat
+} 0 "db9232d96cae7aaba817350ef6cf4c25604d8fd36965f78ceb3ce59fd31ccb2a dgst.dat" 
+
+
+end_tests
diff --git a/tcl_tests/calcstat b/tcl_tests/calcstat
new file mode 100644 (file)
index 0000000..3e59eb6
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/tclsh
+if {$tcl_platform(platform) == "unix"} {
+       fconfigure stdout -translation lf
+}
+lappend auto_path [file dirname [info script]] 
+proc rus {string} {
+       return [encoding convertfrom cp1251 [encoding convertto $string]]
+}
+proc compare_order {el1 el2} {
+       global order
+       return [expr {$order($el1)-$order($el2)}]
+}
+set statsfile stats
+if {$argc} {set statsfile [lindex $argv 0]}
+set f [open $statsfile]
+fconfigure $f -encoding cp1251
+set ordno 0
+while {[gets $f line] >=0} {
+       set script [lindex $line 0]
+       set a($script) [lrange $line 1 end]
+       if {![info exists order($script)]} {
+               set order($script) [incr ordno]
+       }       
+}
+close $f
+
+proc output {line} {
+       global out
+       puts $line
+       if {[info exists out]} {
+               puts $out $line
+       }
+}      
+
+if {$argc > 1} {
+       set out [open [lindex $argv 1] w]
+       fconfigure $out -encoding cp1251
+}      
+
+output [format "%-12s %-41s%5s %4s %4s %4s %4s"  File "Test name" Total ok fail skip ign]  
+output [string repeat "-" 79]
+array set gross {total 0 ok 0 fail 0 p_skip 0 c_skip 0}
+
+
+foreach script [lsort -command compare_order [array names a] ] {
+       foreach {name total ok fail p_skip c_skip} $a($script) break
+       output [format "%-12s %-41s%5d %4d %4d %4d %4d" [string range [file tail [file rootname $script]] 0 11] [string range $name 0 40] $total $ok $fail $p_skip $c_skip]
+       incr gross(total) $total
+       incr gross(ok) $ok
+       incr gross(fail) $fail
+       incr gross(p_skip) $p_skip
+       incr gross(c_skip) $c_skip
+}
+
+output [string repeat "-" 79]
+output [format "%-54s%5d %4d %4d %4d %4d" Total $gross(total) $gross(ok) $gross(fail) $gross(p_skip) $gross(c_skip)]
+
+if {$gross(fail)} {
+       exit 1
+}      
diff --git a/tcl_tests/cbc0.enc b/tcl_tests/cbc0.enc
new file mode 100644 (file)
index 0000000..8ef7d15
--- /dev/null
@@ -0,0 +1,2 @@
+Salted__»d°å\84½1\8e\82ÐÞo\1f\87tV\82ºÙ\8b
+"h;ó\a\ 6\17\9b\87
\ No newline at end of file
diff --git a/tcl_tests/cbc1.enc b/tcl_tests/cbc1.enc
new file mode 100644 (file)
index 0000000..41872cd
--- /dev/null
@@ -0,0 +1,2 @@
+\82ÐÞo\1f\87tV\82ºÙ\8b
+"h;ó\a\ 6\17\9b\87
\ No newline at end of file
diff --git a/tcl_tests/cfb0.enc b/tcl_tests/cfb0.enc
new file mode 100644 (file)
index 0000000..b254385
--- /dev/null
@@ -0,0 +1,2 @@
+Salted__©\84\88¦\1c8\ 3
+i¹«ÊS#Õ@ù\8dÃðgu\19\ 6\93ï$
\ No newline at end of file
diff --git a/tcl_tests/cfb1.enc b/tcl_tests/cfb1.enc
new file mode 100644 (file)
index 0000000..e103ace
--- /dev/null
@@ -0,0 +1,2 @@
+i¹«ÊS#Õ@ù\8dÃðgu\19\ 6\93ï$
\ No newline at end of file
diff --git a/tcl_tests/ciphers.try b/tcl_tests/ciphers.try
new file mode 100644 (file)
index 0000000..ae75759
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/tclsh
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir 
+start_tests "Тесты на команду ciphers"
+
+proc find_ciphers {openssl_args globpattern} {
+       set found [lsort [lsearch -all -inline [split [string trim [grep $globpattern [openssl $openssl_args] ] "\n" ] : ] "$globpattern*"] ]
+       return $found
+}
+
+test "Проверяем поддержку российских алгоритмов в tls" {
+       find_ciphers "ciphers" "GOST"
+} 0 {GOST2001-GOST89-GOST89 GOST2012-GOST8912-GOST8912}
+
+test "Проверяем поддержку российских алгоритмов без шифрования в tls" {
+       find_ciphers "ciphers NULL" "GOST"
+} 0 {GOST2001-NULL-GOST94 GOST2012-NULL-GOST12}
+
+#test "Проверяем отсутствие российских алгоритмов в ssl2" {
+#      find_ciphers "ciphers -ssl2" "GOST"
+#} 0 ""
+
+#test "Проверяем работоспособность команды ciphers" {
+#      find_ciphers "ciphers AES" "AES"
+#} 0 {"ADH-AES256-SHA"
+#"DHE-RSA-AES256-SHA"
+#"DHE-DSS-AES256-SHA"
+#"AES256-SHA"
+#"ADH-AES128-SHA"
+#"DHE-RSA-AES128-SHA"
+#"DHE-DSS-AES128-SHA"
+#"AES128-SHA"
+#}
+
+
+end_tests
+
diff --git a/tcl_tests/client.try b/tcl_tests/client.try
new file mode 100644 (file)
index 0000000..d6abcb3
--- /dev/null
@@ -0,0 +1,143 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+
+package require ossltest
+
+if {$argc != 1} {
+       puts stderr "Usage $argv0 cipher-list-file"
+       exit 1
+}      
+
+array set protos {
+       SSLv2 -ssl2
+       SSLv3 -ssl3
+       TLSv1 -tls1
+       TLSv1.1 -tls1_1
+       TLSv1.2 -tls1_2
+    "default" {}
+}      
+get_hosts [lindex $argv 0]
+cd $::test::dir 
+start_tests "TLS-соединение от клиента [lindex $argv 0]"
+
+set CAhost lynx.lan.cryptocom.ru
+set CAprefix /cgi-bin/autoca
+
+
+foreach alg [array names hosts] {
+       set alg2 [regsub {(gost\d+)cp} $alg {\1}]
+       set alg_fn [string map {":" "_"} $alg2]
+       set alg_ca [regexp -inline {^[^:]+} $alg]
+       log "alg_fn=$alg_fn"
+       if {[string match gost2001* $alg]} {
+                set alg_cli_list "gost2001_A gost2001_XA"
+        } elseif {[string match gost2012* $alg]} {
+                set alg_cli_list "gost2001_A gost2012_256_A gost2012_256_XA gost2012_512_A gost2012_512_B"
+       } else {
+               set alg_cli_list $alg_ca
+       }
+
+
+       test -skip {[file exist ca_$alg_ca.pem]} "Получить сертификат $alg_ca CA" {
+               getCAcert $CAhost $CAprefix $alg_ca
+       } 0 "ca_$alg_ca.pem"
+
+       test -skip {[file exist srv_$alg_fn/cert.pem]} "Получить сертификат $alg для сервера" {
+               getCAAlgParams $CAhost $CAprefix $alg_ca
+               if {![makeUser srv_$alg_fn $alg2 CN [info hostname]]} {
+                       error "Request generation failed"
+               }
+               registerUserAtCA srv_$alg_fn $CAhost $CAprefix $alg_ca
+               file exists srv_$alg_fn/cert.pem
+       } 0 1
+
+       if {[array exists suites]} {array unset suites}
+       array set suites $hosts($alg)
+       foreach suite [array names suites] {
+               if {![regexp {(.+):(.+)} $suite => proto cs]} {
+                       set cs $suite
+                       set proto "default"
+               }       
+               if {[info exists suite_map($cs)]} {
+                       set mycs $suite_map($cs)
+               } else {
+                       set mycs $cs
+               }       
+               set host [lindex [split $suites($suite) :] 0]
+               set host_short [lindex [split $host .] 0]
+               # We assume that CA certificates are already copied into Apache
+               # cert dir
+               set ca_file "/etc/apache/ssl.crt/${alg_ca}-root.crt"
+
+               test "Корректный хэндшейк $suite" {
+                       remote_client $host
+                       set list [client_server [list -connect [info hostname]:4433 \
+                               -CAfile $ca_file -state -cipher $cs] \
+                               [concat [list -www -cert srv_$alg_fn/cert.pem \
+                               -key srv_$alg_fn/seckey.pem -cipher $mycs] $protos($proto)] {}]
+                       set cln_exit_code [lindex $list 2]
+                       set srv_error [string match "*error*" [lindex $list 4]]
+                       if {[regexp -lineanchor \
+                       {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                       [lindex $list 0] -> result_proto result_cipher]} {
+                               if {$proto == "default"} {set result_proto "default"}
+                               list $cln_exit_code $srv_error $result_proto $result_cipher
+                       } else {
+                               lindex $list 1
+                       }       
+               } 0 [list 0 0 $proto $cs]
+
+
+               test "Сервер требует сертификат, сертификата нет $suite" {
+                       remote_client $host
+                       set list [client_server [list -connect [info hostname]:4433 \
+                               -CAfile $ca_file -state -cipher $cs] \
+                               [concat [list -www -cert srv_$alg_fn/cert.pem \
+                               -key srv_$alg_fn/seckey.pem -cipher $mycs -Verify 3 \
+                               -verify_return_error] $protos($proto)] {}]
+                       string match "*error*" [lindex $list 4]
+               } 0 1 
+
+
+               test "Некорректный клиентский сертфиикат $suite" {
+                       remote_client $host
+                       set list [client_server [list -connect [info hostname]:4433 \
+                               -cert /home/build/client-$alg_ca/cert.pem \
+                               -key /home/build/client-$alg_ca/seckey.pem \
+                               -CAfile $ca_file -state -cipher $cs] \
+                               [concat [list -www -cert srv_$alg_fn/cert.pem \
+                               -key srv_$alg_fn/seckey.pem -cipher $mycs -Verify 3 \
+                               -verify_return_error] $protos($proto)] {}]
+                       string match "*error*" [lindex $list 4]
+               } 0 1
+
+
+
+               foreach alg_cli $alg_cli_list {
+
+                       test "Клиентский сертификат $alg_cli $suite" {
+                               remote_client $host
+                               set list [client_server [list -connect [info hostname]:4433 \
+                                       -cert /home/build/client-$alg_cli/cert.pem \
+                                       -key /home/build/client-$alg_cli/seckey.pem \
+                                       -CAfile $ca_file -state -cipher $cs] \
+                                       [concat [list -www -cert srv_$alg_fn/cert.pem \
+                                       -key srv_$alg_fn/seckey.pem -CAfile ca_$alg_ca.pem \
+                                       -cipher $mycs -Verify 3 -verify_return_error] \
+                                       $protos($proto)] {}]
+                               set cln_exit_code [lindex $list 2]
+                               set srv_error [string match "*error*" [lindex $list 4]]
+                               if {[regexp -lineanchor \
+                               {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                               [lindex $list 0] -> result_proto result_cipher]} {
+                                       if {$proto == "default"} {set result_proto "default"}
+                                       list $cln_exit_code $srv_error $result_proto $result_cipher
+                               } else {
+                                       lindex $list 1
+                               }       
+                       } 0 [list 0 0 $proto $cs]
+               }
+       }
+}      
+end_tests
diff --git a/tcl_tests/cms.try b/tcl_tests/cms.try
new file mode 100644 (file)
index 0000000..476da0d
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на команду cms" 
+
+test "Creating CA 2001" {
+       makeCA ${testname}CA gost2001:A
+} 0 1
+
+test "Creating CA 2012" {
+       makeCA
+} 0 1
+
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_cms_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca ${testname}CA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca ${testname}CA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+
+test "Creating user with signing 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
+
+test -skip {![file exists $username/cert.pem]} -createsfiles [list cms_sign.dat cms_sign_$alg_fn.msg] "Signing a message without cert by $alg" {
+       makeFile cms_sign.dat [string repeat "Test data to cms_sign.\n" 100] 
+       openssl "cms -sign -in cms_sign.dat -text -out cms_sign_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nocerts"
+       file isfile cms_sign_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist cms_sign_$alg_fn.msg]} "Checking micalg param in signed without cert $alg message" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile cms_sign_$alg_fn.msg]]
+} 0 1
+
+test -createsfiles cms_sign_$alg_fn.pem -skip {![file exist cms_sign_$alg_fn.msg]} "Extracting CMS from signed without cert $alg message" {
+       openssl "cms -cmsout -out cms_sign_$alg_fn.pem -outform PEM -in cms_sign_$alg_fn.msg"
+       file isfile cms_sign_$alg_fn.pem
+} 0 1
+
+
+test -skip {![file exists cms_sign_$alg_fn.pem]} "Checking oids in cms struct" {
+       extract_oids cms_sign_$alg_fn.pem PEM
+} 0 [mkObjList [hash_long_name $alg] [hash_long_name $alg] "GOST R 34.11-2012 with 256 bit hash" "GOST R 34.11-2012 with 512 bit hash" "GOST R 34.11-94" "GOST 28147-89" [alg_long_name $alg]]  
+# hash_12_256 hash_12_512 hash_94 crypt89_cc are from sMIMECapabilities
+
+test -skip {![file exists cms_sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca " {
+       grep Veri [openssl "cms -verify -text -in cms_sign_$alg_fn.msg -out cms_verified.txt -noverify -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca" {
+       grep Veri [openssl "cms -verify -text -in cms_sign_$alg_fn.msg -out cms_verified.txt -certfile $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_$alg_fn.msg]} -createsfiles [list cms_bad_$alg_fn.msg cms_verified.txt] "Verifying corrupted messages signed with $alg" {
+       set corrupted [getFile cms_sign_$alg_fn.msg]
+       set index [string first "Test data" $corrupted ]
+       makeFile cms_bad_$alg_fn.msg [string replace $corrupted $index [expr $index+9] "Bad data"]
+       grep Verification [openssl "cms -verify -text -in cms_bad_$alg_fn.msg -out cms_verified.txt -noverify -certfile $username/cert.pem"]
+} 1 "Verification failure"
+
+test -skip {![file exists $username/cert.pem]}  -createsfiles [list cms_sign.dat cms_sign_c_$alg_fn.msg] "Signing a message by $alg with cert" {
+       makeFile cms_sign.dat [string repeat "Test data to sign.\n" 100] 
+       openssl "cms -sign -in cms_sign.dat -crlfeol -text -out cms_sign_c_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+       file isfile cms_sign_c_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist cms_sign_c_$alg_fn.msg]} "Checking micalg param in signed with cert $alg message" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile cms_sign_c_$alg_fn.msg]]
+} 0 1
+
+test -skip {![file exists cms_sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca" {
+       grep Veri [openssl "cms -verify -text -in cms_sign_c_$alg_fn.msg -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca" {
+       grep Veri [openssl "cms -verify -text -in cms_sign_c_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists $username/cert.pem]} -createsfiles {cms_sign.dat cms_sign_op_$alg_fn.msg} "Signing a message by $alg with cert using opaque signing" {
+       makeFile cms_sign.dat [string repeat "Test data to cms_sign.\n" 100] 
+       openssl "cms -sign -in cms_sign.dat -text -out cms_sign_op_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nodetach"
+       file isfile cms_sign_op_$alg_fn.msg
+} 0 1
+
+test -createsfiles cms_verified.txt -skip {![file exists cms_sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca" {
+       grep Veri [openssl "cms -verify -text -in cms_sign_op_$alg_fn.msg -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -createsfiles cms_verified.txt -skip {![file exists cms_sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca" {
+       grep Veri [openssl "cms -verify -text -in cms_sign_op_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -createsfiles cms_broken_op_$alg_fn.msg  -skip {![file exists cms_sign_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       set data [getFile cms_sign_op_$alg_fn.msg]
+       regexp "(.*)\n\r?\n(.+)" $data match header encoded
+       set asnstruct [::base64::decode $encoded]
+       makeFile cms_broken_op_$alg_fn.msg "$header\n\n[::base64::encode [regsub -all\
+               "Test data" $asnstruct "Best data"]]"
+       grep Verification [openssl "cms -verify -text -in cms_broken_op_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+       
+
+test -createsfiles "cms_sign_det_$alg_fn.msg" -skip {![file exists $username/cert.pem]||![file exists cms_sign.dat]} "Creating detached $alg signature" {
+       openssl "cms -sign -binary -in cms_sign.dat -out cms_sign_det_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+       file exists cms_sign_det_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist cms_sign_det_$alg_fn.msg]} "Checking micalg param in detached $alg signature" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile cms_sign_det_$alg_fn.msg]]
+} 0 1
+
+test -createsfiles cms_sign_det_$alg_fn.pem -skip {![file exist cms_sign_det_$alg_fn.msg]} "Extracting CMS from signed $alg message" {
+openssl "cms -cmsout -out cms_sign_det_$alg_fn.pem -outform PEM -in cms_sign_det_$alg_fn.msg"
+       file isfile cms_sign_$alg_fn.pem
+} 0 1
+
+#We expect cryptocom oids because of cert cms_signed by ca with Cryptocom algs
+# Result sequence
+# 1. digest 
+# 2.  algorithm of CA key
+# 3. algorithm of current key
+# 4. algorithm of CA key
+# 5. digest
+# 6. digests from sMIMECapabilities
+# 7. encryption from sMIMECapabilities
+# 8. algorithm of current key
+test -skip {![file exists cms_sign_$alg_fn.pem]} "Checking oids in cms struct" {
+       extract_oids cms_sign_det_$alg_fn.pem PEM
+} 0 [mkObjList [hash_long_name $alg] [smime_hash_with_sign_long_name $ca_sign_alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [smime_hash_with_sign_long_name  $ca_sign_alg] [hash_long_name $alg] "GOST R 34.11-2012 with 256 bit hash" "GOST R 34.11-2012 with 512 bit hash" "GOST R 34.11-94" "GOST 28147-89" [alg_long_name $alg]]
+
+test -skip {![file exists cms_sign_det_$alg_fn.pem]} "Verifying detached $alg cms_signature" {
+       grep Veri [openssl "cms -verify -content cms_sign.dat -inform PEM -in cms_sign_det_$alg_fn.pem -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_det_$alg_fn.msg]} -createsfiles {bad.dat} "Verifying corrupted $alg detached cms_signature" {
+       makeFile bad.dat [regsub Test [getFile cms_sign.dat] Best]
+       grep Verification [openssl "cms -verify -content bad.dat -in cms_sign_det_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+
+
+}
+end_tests
diff --git a/tcl_tests/cms2.try b/tcl_tests/cms2.try
new file mode 100644 (file)
index 0000000..1233d55
--- /dev/null
@@ -0,0 +1,207 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду cms - вторая подпись" 
+
+test "Creating CA" {
+       makeCA
+} 0 1
+
+makeFile cms_signed2.dat "Test data for 2 signatures"
+
+
+foreach length {256 512} {
+
+test "Creating users $length" {
+       makeRegisteredUser U_cms_1_$length gost2012_$length:A CN USER1_$length emailAddress test@cryptocom.ru
+       makeRegisteredUser U_cms_2_$length gost2012_$length:A CN USER2_$length emailAddress test@cryptocom.ru
+} 0 1
+
+test -createsfiles cms_signed2_1_$length.asn "Signing in DER format with 1st signature" {
+       openssl "cms -sign -binary -outform der -inform der -nodetach -inkey U_cms_1_$length/seckey.pem -signer U_cms_1_$length/cert.pem -in cms_signed2.dat -out cms_signed2_1_$length.asn"
+       file isfile cms_signed2_1_$length.asn
+} 0 1
+
+test -createsfiles cms_signed2_2_$length.asn "Signing in DER format with 2nd signature" {
+       openssl "cms -resign -binary -outform der -inform der -nodetach -inkey U_cms_2_$length/seckey.pem -signer U_cms_2_$length/cert.pem -in cms_signed2_1_$length.asn -out cms_signed2_2_$length.asn"
+       file isfile cms_signed2_2_$length.asn
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying signature in DER format" {
+       grep "Verif" [openssl "cms -verify -inform der -in cms_signed2_2_$length.asn -noverify -signer signer.certs -out was_signed.dat"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile cms_signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles cms_signed2_1_$length\_op.msg "Signing opaque in S/MIME format with 1st signature" {
+       openssl "cms -sign -binary -inform der -nodetach -inkey U_cms_1_$length/seckey.pem -signer U_cms_1_$length/cert.pem -in cms_signed2.dat -out cms_signed2_1_$length\_op.msg"
+       file isfile cms_signed2_1_$length\_op.msg
+} 0 1
+
+test -createsfiles cms_signed2_2_$length\_op.msg "Signing opaque in S/MIME format with 2nd signature" {
+       openssl "cms -resign -binary -nodetach -inkey U_cms_2_$length/seckey.pem -signer U_cms_2_$length/cert.pem -in cms_signed2_1_$length\_op.msg -out cms_signed2_2_$length\_op.msg"
+       file isfile cms_signed2_2_$length\_op.msg
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying opaque signature in S/MIME format" {
+       grep "Verif" [openssl "cms -verify -in cms_signed2_2_$length\_op.msg -noverify -signer signer.certs -out was_signed.dat"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile cms_signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0 "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles cms_signed2_1_$length\_det.asn "Signing detached in DER format with 1st signature" {
+       openssl "cms -sign -binary -outform der -inkey U_cms_1_$length/seckey.pem -signer U_cms_1_$length/cert.pem -in cms_signed2.dat -out cms_signed2_1_$length\_det.asn"
+       file isfile cms_signed2_1_$length\_det.asn
+} 0 1
+
+test -createsfiles cms_signed2_2_$length\_det.asn "Signing detached in DER format with 2nd signature" {
+       openssl "cms -resign -binary -inkey U_cms_2_$length/seckey.pem -signer U_cms_2_$length/cert.pem -in cms_signed2_1_$length\_det.asn -content cms_signed2.dat -inform der -outform der -out cms_signed2_2_$length\_det.asn"
+       file isfile cms_signed2_2_$length\_det.asn
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying detached signature in DER format" {
+       grep "Verif" [openssl "cms -verify -in cms_signed2_2_$length\_det.asn -noverify -signer signer.certs -out was_signed.dat -content signed2.dat -inform der"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile cms_signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert_asn[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert_asn$i.pem -subject -noout"]]
+       }
+       lsort  $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles cms_signed2_1_$length.msg "Signing in S/MIME format with 1st signature" {
+       openssl "cms -sign -binary -inform der -inkey U_cms_1_$length/seckey.pem -signer U_cms_1_$length/cert.pem -in cms_signed2.dat -out cms_signed2_1_$length.msg"
+       file isfile cms_signed2_1_$length.msg
+} 0 1
+
+test -createsfiles cms_signed2_2_$length.msg "Signing in S/MIME format with 2nd signature" {
+       grep "SMIME" [openssl "cms -resign -binary -inkey U_cms_2_$length/seckey.pem -signer U_cms_2_$length/cert.pem -in cms_signed2_1_$length.msg -inform smime -out cms_signed2_2_$length.msg"]
+} 0 ""
+
+test -createsfiles {was_signed.dat  signer.certs} "Verifying signature in S/MIME format" {
+       grep "Verif" [openssl "cms -verify -in cms_signed2_2_$length.msg -noverify -signer signer.certs -out was_signed.dat -inform smime"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile cms_signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert_cms[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert_cms$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+}
+
+
+test "Resigning in DER format with a unsuitable key length 512" {
+       openssl "cms -resign -binary -inform der -nodetach -inkey U_cms_2_512/seckey.pem -signer U_cms_2_512/cert.pem -in cms_signed2_1_256.asn"
+} 1 "no matching digest"
+
+test "Resigning in DER format with a unsuitable key length 256" {
+       openssl "cms -resign -binary -inform der -nodetach -inkey U_cms_2_256/seckey.pem -signer U_cms_2_256/cert.pem -in cms_signed2_1_512.asn"
+} 1 "no matching digest"
+
+test "Resigning opaque in S/MIME format with a unsuitable key length 512" {
+       openssl "cms -resign -binary -nodetach -inkey U_cms_2_512/seckey.pem -signer U_cms_2_512/cert.pem -in cms_signed2_1_256_op.msg"
+} 1 "no matching digest"
+
+test "Resigning opaque in S/MIME format with a unsuitable key length 256" {
+       openssl "cms -resign -binary -nodetach -inkey U_cms_2_256/seckey.pem -signer U_cms_2_256/cert.pem -in cms_signed2_1_512_op.msg"
+} 1 "no matching digest"
+
+test "Resigning detached in DER format with a unsuitable key length 512" {
+       openssl "cms -resign -binary -inform der -inkey U_cms_2_512/seckey.pem -signer U_cms_2_512/cert.pem -in cms_signed2_1_256_det.asn -content cms_signed2.dat"
+} 1 "no matching digest"
+
+test "Resigning detached in DER format with a unsuitable key length 256" {
+       openssl "cms -resign -binary -inform der -inkey U_cms_2_256/seckey.pem -signer U_cms_2_256/cert.pem -in cms_signed2_1_512_det.asn -content cms_signed2.dat"
+} 1 "no matching digest"
+
+test "Resigning in S/MIME format with a unsuitable key length 512" {
+       openssl "cms -resign -binary -inkey U_cms_2_512/seckey.pem -signer U_cms_2_512/cert.pem -in cms_signed2_1_256.msg"
+} 1 "no matching digest"
+
+test "Resigning in S/MIME format with a unsuitable key length 256" {
+       openssl "cms -resign -binary -inkey U_cms_2_256/seckey.pem -signer U_cms_2_256/cert.pem -in cms_signed2_1_512.msg"
+} 1 "no matching digest"
+
+
+end_tests
+
+
+
+#./load_engine cms -sign -binary -outform der -inform der -nodetach -inkey certs/fstek.key -signer certs/fstek.crt -out cms_signed2 -in cms_signed1
+#./load_engine cms -verify -inform der -in cms_signed2 -noverify
+#./load_engine cms -verify -inform der -in cms_signed2 -noverify -signer sss
+#cat sss
+#history 
+#vim sss
+#./load_engine x509 -in sss sss2
+#./load_engine x509 -in sss 
+#./load_engine x509 -in sss -subject -noout
+#./load_engine x509 -in sss2 -subject -noout
+#./load_engine cms -verify -inform der -in cms_signed2 -noverify -signer sss -out qqq
diff --git a/tcl_tests/cms_cs.try b/tcl_tests/cms_cs.try
new file mode 100644 (file)
index 0000000..d246fe8
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на интероперабельность результатов подписи командой cms с smime-проверками на эталонниках" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_cms_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca cmsCA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca cmsCA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+set hosts [list tls-ref-cp21]
+foreach hstname $hosts {
+
+
+#test -skip {![file exists $username/cert.pem]} -createsfiles [list sign.dat sign_$alg_fn.msg] "Signing a message by smime without cert by $alg (verify by smime)" {
+#      makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+#      openssl "cms -sign -in sign.dat -text -out sign_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nocerts"
+#      file isfile sign_$alg_fn.msg
+#} 0 1
+
+test -skip {![file exists sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca via smime" {
+       grep Veri [openssl_remote "$username sign_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_$alg_fn.msg -out TESTPATH/verified.txt -noverify -certfile TESTPATH/$username/cert.pem" "cms"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca via smime" {
+       grep Veri [openssl_remote "$::test::ca sign_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_$alg_fn.msg -out TESTPATH/verified.txt -certfile TESTPATH/$username/cert.pem -CAfile TESTPATH/$::test::ca/cacert.pem" "cms"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]} -createsfiles [list bad_$alg_fn.msg TESTPATH/verified.txt] "Verifying corrupted messages signed with $alg via smime" {
+       set corrupted [getFile sign_$alg_fn.msg]
+       set index [string first "Test data" $corrupted ]
+       makeFile bad_$alg_fn.msg [string replace $corrupted $index [expr $index+9] "Bad data"]
+       grep Verification [openssl_remote "bad_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/bad_$alg_fn.msg -out TESTPATH/verified.txt -noverify -certfile TESTPATH/$username/cert.pem" "cms"]
+} 1 "Verification failure"
+
+#test -skip {![file exists $username/cert.pem]}  -createsfiles [list sign.dat sign_c_$alg_fn.msg] "Signing a message by $alg with cert" {
+#      makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+#      openssl "cms -sign -in sign.dat -crlfeol -text -out sign_c_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+#      file isfile sign_c_$alg_fn.msg
+#} 0 1
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca via smime" {
+       grep Veri [openssl_remote "sign_c_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_c_$alg_fn.msg -out TESTPATH/verified.txt -noverify" "cms"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca via smime" {
+       grep Veri [openssl_remote "sign_c_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_c_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "cms"]
+} 0 "Verification successful
+"
+
+#test -skip {![file exists $username/cert.pem]} -createsfiles {sign.dat sign_op_$alg_fn.msg} "Signing a message by $alg with cert using opaque signing" {
+#      makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+#      openssl "cms -sign -in sign.dat -text -out sign_op_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nodetach"
+#      file isfile sign_op_$alg_fn.msg
+#} 0 1
+
+test -createsfiles TESTPATH/verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca via smime" {
+       grep Veri [openssl_remote "sign_op_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_op_$alg_fn.msg -out TESTPATH/verified.txt -noverify" "cms"]
+} 0 "Verification successful
+"
+
+test -createsfiles TESTPATH/verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca via smime" {
+       grep Veri [openssl_remote "sign_op_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/sign_op_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "cms"]
+} 0 "Verification successful
+"
+
+test -createsfiles broken_op_$alg_fn.msg  -skip {![file exists sign_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       set data [getFile sign_op_$alg_fn.msg]
+       regexp "(.*)\n\r?\n(.+)" $data match header encoded
+       set asnstruct [::base64::decode $encoded]
+       makeFile broken_op_$alg_fn.msg "$header\n\n[::base64::encode [regsub -all\
+               "Test data" $asnstruct "Best data"]]"
+       grep Verification [openssl_remote "broken_op_$alg_fn.msg" "$hstname" "smime -verify -text -in TESTPATH/broken_op_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "cms"]
+} 1 "Verification failure"
+
+#test -createsfiles "sign_det_$alg_fn.msg" -skip {![file exists $username/cert.pem]||![file exists sign.dat]} "Creating detached $alg signature" {
+#      openssl "cms -sign -binary -in sign.dat -out sign_det_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+#      file exists sign_det_$alg_fn.msg
+#} 0 1
+
+#We expect cryptocom oids because of cert signed by ca with Cryptocom algs
+# Result sequence
+# 1. digest 
+# 2.  algorithm of CA key
+# 3. algorithm of current key
+# 4. algorithm of CA key
+# 5. digest
+# 6. digests from sMIMECapabilities
+# 7. encryption from sMIMECapabilities
+# 8. algorithm of current key
+
+test -skip {![file exists pk7sign_$alg_fn.pem]} "Verifying detached $alg signature via smime" {
+       grep Veri [openssl_remote "pk7sign_$alg_fn.pem sign.dat" "$hstname" "smime -verify -content TESTPATH/sign.dat -inform PEM -in TESTPATH/pk7sign_$alg_fn.pem -out TESTPATH/verified.txt -noverify" "cms"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists pk7sign_$alg_fn.pem]} -createsfiles {bad.dat} "Verifying corrupted $alg detached signature" {
+       makeFile bad.dat [regsub Test [getFile sign.dat] Best]
+       grep Verification [openssl_remote "sign_det_$alg_fn.msg bad.dat" "$hstname" "smime -verify -content TESTPATH/bad.dat -in TESTPATH/sign_det_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "cms"]
+} 1 "Verification failure"
+}
+
+}
+end_tests
diff --git a/tcl_tests/cms_io.try b/tcl_tests/cms_io.try
new file mode 100644 (file)
index 0000000..92c3619
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на совместтимость cms и smime -sign" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_cms_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca cmsCA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca cmsCA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+
+test -skip {![file exists cms_sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca " {
+       grep Veri [openssl "smime -verify -text -in cms_sign_$alg_fn.msg -out cms_verified.txt -noverify -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca" {
+       grep Veri [openssl "smime -verify -text -in cms_sign_$alg_fn.msg -out cms_verified.txt -certfile $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_bad_$alg_fn.msg]} -createsfiles cms_verified.txt "Verifying corrupted messages signed with $alg" {
+       grep Verification [openssl "smime -verify -text -in cms_bad_$alg_fn.msg -out cms_verified.txt -noverify -certfile $username/cert.pem"]
+} 1 "Verification failure"
+
+test -skip {![file exists cms_sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca" {
+       grep Veri [openssl "smime -verify -text -in cms_sign_c_$alg_fn.msg -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca" {
+       grep Veri [openssl "smime -verify -text -in cms_sign_c_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -createsfiles cms_verified.txt -skip {![file exists cms_sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca" {
+       grep Veri [openssl "smime -verify -text -in cms_sign_op_$alg_fn.msg -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -createsfiles cms_verified.txt -skip {![file exists cms_sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca" {
+       grep Veri [openssl "smime -verify -text -in cms_sign_op_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_broken_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       grep Verification [openssl "smime -verify -text -in cms_broken_op_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+       
+test -skip {![file exists cms_sign_det_$alg_fn.msg]} "Verifying detached $alg signature" {
+       grep Veri [openssl "smime -verify -content cms_sign.dat -in cms_sign_det_$alg_fn.msg -out cms_verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists cms_sign_det_$alg_fn.msg]} -createsfiles {bad.dat} "Verifying corrupted $alg detached signature" {
+       makeFile bad.dat [regsub Test [getFile cms_sign.dat] Best]
+       grep Verification [openssl "smime -verify -content bad.dat -in cms_sign_det_$alg_fn.msg -out cms_verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+
+
+}
+end_tests
diff --git a/tcl_tests/cmsenc.try b/tcl_tests/cmsenc.try
new file mode 100644 (file)
index 0000000..6608226
--- /dev/null
@@ -0,0 +1,190 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на cms -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_cms_enc_rsa_1 U_cms_enc_rsa_2} {
+test "Make registered user $user" {
+       makeRegisteredUser $user rsa:512 CAname ${testname}CA-RSA
+} 0 1
+}
+
+
+test -createsfiles cms_enc_rsa.msg "RSA User 1 encrypts message for RSA user 2" {
+       openssl "cms -encrypt -in encrypt.dat -des -out cms_enc_rsa.msg U_cms_enc_rsa_2/cert.pem"
+       file isfile cms_enc_rsa.msg
+} 0 1
+
+test "RSA User 1 cannot decrypt message for RSA user 2" {
+       grep "Error"    [openssl "cms -decrypt -in cms_enc_rsa.msg -recip U_cms_enc_rsa_1/cert.pem -inkey U_cms_enc_rsa_1/seckey.pem"]
+} 1 {Error decrypting CMS}
+
+test -createsfiles cms_decrypt.rsa "RSA User 2 (with cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in cms_enc_rsa.msg -recip U_cms_enc_rsa_2/cert.pem -inkey U_cms_enc_rsa_2/seckey.pem -out cms_decrypt.rsa"
+       set result [getFile cms_decrypt.rsa]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles cms_decrypt_nocert.rsa "RSA User 2 (without cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in cms_enc_rsa.msg -inkey U_cms_enc_rsa_2/seckey.pem -out cms_decrypt_nocert.rsa"
+       set result [getFile cms_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 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:}}
+       }
+}
+
+save_env2 {OPENSSL_CONF CRYPT_PARAMS}
+makeFile cmsenc1.cnf [regsub -all "\n\\s*CRYPT_PARAMS\\s*=\[\^\n]*" [getConfig] ""]
+set ::env(OPENSSL_CONF) [file join [pwd] cmsenc1.cnf]
+
+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_cms_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 cms_enc_$alg_fn.msg "Encrypting for $username" {
+       grep "rror" [openssl "cms -encrypt -in encrypt.dat -gost89 -out cms_enc_$alg_fn.msg U_cms_enc_$alg_fn/cert.pem"]
+} 0 ""
+
+if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+test -createsfiles cms_enc_$alg_fn.pem "Extracting CMS from encrypted structure for $username" {
+       openssl "cms -cmsout -out cms_enc_$alg_fn.pem -outform PEM -in cms_enc_$alg_fn.msg"
+       file isfile cms_enc_$alg_fn.pem
+} 0 1
+
+test -skip {![file exists cms_enc_$alg_fn.pem]} "Checking oids in pkcs7 structure for $username" {
+       extract_oids cms_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 cms_decrypt.$alg_fn "Decrypting file encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in cms_enc_$alg_fn.msg -recip U_cms_enc_$alg_fn/cert.pem -inkey U_cms_enc_$alg_fn/seckey.pem -out cms_decrypt.$alg_fn"
+       set result [getFile cms_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 cms_enc_t_$alg_fn.msg "Encrypting for $username - text format" {
+       grep "rror" [openssl "cms -encrypt -text -in encrypt.dat -gost89 -out cms_enc_t_$alg_fn.msg U_cms_enc_$alg_fn/cert.pem"]
+} 0 ""
+
+if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+test -createsfiles cms_decrypt_t.$alg_fn "Decrypting file text-encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -text -in cms_enc_t_$alg_fn.msg -recip U_cms_enc_$alg_fn/cert.pem -inkey U_cms_enc_$alg_fn/seckey.pem -out cms_decrypt_t.$alg_fn"
+       set result [getFile cms_decrypt_t.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles cms_decrypt_t_nocert.$alg_fn "Decrypting file text-encrypted for $username without cert" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -text -in cms_enc_t_$alg_fn.msg -inkey U_cms_enc_$alg_fn/seckey.pem -out cms_decrypt_t_nocert.$alg_fn"
+       set result [getFile cms_decrypt_t_nocert.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+}
+
+
+test -createfiles cms_enc_4all "Encrypt for all" {
+       grep "rror" [openssl "cms -encrypt -in encrypt.dat -gost89 -out cms_enc_4all.msg [map {U_cms_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_cms_enc_$alg_fn
+       
+test -skip {![file exists cms_enc_4all.msg]} -createsfiles cms_decrypt_4all.$alg_fn "Decrypting gost-encrypted file, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in cms_enc_4all.msg -recip $username/cert.pem -inkey $username/seckey.pem -out cms_decrypt_4all.$alg_fn"
+       set result [getFile cms_decrypt_4all.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -skip {![file exists cms_enc_4all.msg]} -createsfiles cms_decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in cms_enc_4all.msg -inkey $username/seckey.pem -out cms_decrypt_4all_nocert.$alg_fn"
+       set result [getFile cms_decrypt_4all_nocert.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+}
+
+restore_env2 {OPENSSL_CONF CRYPT_PARAMS}
+
+end_tests
diff --git a/tcl_tests/cmsenc_cs.try b/tcl_tests/cmsenc_cs.try
new file mode 100644 (file)
index 0000000..3ae497e
--- /dev/null
@@ -0,0 +1,215 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+package require test
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на cms -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
+#
+
+set ::test::ca cmsencCA-RSA
+
+#foreach user {U_cms_enc_rsa_1 U_cms_enc_rsa_2} {
+#test "Make registered user $user" {
+#      makeRegisteredUser $user rsa:512 CAname ${testname}CA-RSA
+#} 0 1
+#}
+
+set hosts tls-ref-cp21
+foreach hstname $hosts {
+
+#test -createsfiles cms_enc_rsa.msg "RSA User 1 encrypts message for RSA user 2" {
+#      openssl "cms -encrypt -in encrypt.dat -des -out cms_enc_rsa.msg U_cms_enc_rsa_2/cert.pem"
+#      file isfile cms_enc_rsa.msg
+#} 0 1
+
+test "RSA User 1 cannot decrypt message for RSA user 2" {
+       grep "Error"    [openssl_remote "cms_enc_rsa.msg U_cms_enc_rsa_1" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -recip TESTPATH/U_cms_enc_rsa_1/cert.pem -inkey TESTPATH/U_cms_enc_rsa_1/seckey.pem" "rsa"]
+} 1 {Error decrypting CMS}
+
+test -skip {![file exists cms_decrypt.rsa]} "RSA User 2 (with cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl_remote "U_cms_enc_rsa_2" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -recip TESTPATH/U_cms_enc_rsa_2/cert.pem -inkey TESTPATH/U_cms_enc_rsa_2/seckey.pem -out TESTPATH/cms_decrypt.rsa" "rsa"
+       set result [getFile cms_decrypt.rsa]
+       string eq $expected $result
+} 0 1
+
+test -skip{![file exists cms_decrypt_nocert.rsa]} "RSA User 2 (without cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl_remote "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -inkey TESTPATH/U_cms_enc_rsa_2/seckey.pem -out TESTPATH/cms_decrypt_nocert.rsa" "rsa"
+       set result [getFile cms_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
+#
+
+set hosts [list tls-ref-cp21 tls-ref-cp20]
+foreach hstname $hosts {
+
+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 }}
+               "open" {set enc_list {gost2001:XA:1.2.643.2.2.31.3 gost2001:XB:1.2.643.2.2.31.4 }}
+       }
+}
+
+save_env2 {OPENSSL_CONF CRYPT_PARAMS}
+makeFile cmsenc1.cnf [regsub -all "\n\\s*CRYPT_PARAMS\\s*=\[\^\n]*" [getConfig] ""]
+set ::env(OPENSSL_CONF) [file join [pwd] cmsenc1.cnf]
+
+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_cms_enc_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca cmsCA-2012}
+               * {set ::test::ca cmsCA}
+       }
+
+#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 cms_enc_$alg_fn.msg "Encrypting for $username" {
+#      grep "rror" [openssl "cms -encrypt -in encrypt.dat -gost89 -out cms_enc_$alg_fn.msg U_cms_enc_$alg_fn/cert.pem"]
+#} 0 ""
+
+if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+#test -createsfiles cms_enc_$alg_fn.pem "Extracting CMS from encrypted structure for $username" {
+#      openssl "cms -cmsout -out cms_enc_$alg_fn.pem -outform PEM -in cms_enc_$alg_fn.msg"
+#      file isfile cms_enc_$alg_fn.pem
+#} 0 1
+
+#test -skip {![file exists cms_enc_$alg_fn.pem]} "Checking oids in pkcs7 structure for $username" {
+#      extract_oids cms_enc_$alg_fn.pem PEM
+#} 0 [mkObjList [alg_id $alg] [param_pubkey $alg] [param_hash $alg] crypt89_cc [param_encr $crypt_param]]
+
+#test "Decrypting file encrypted for $username" {
+#      set expected [getFile encrypt.dat]
+#      openssl_remote "$username U_cms_enc_$alg_fn cms_enc_$alg_fn.msg" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_$alg_fn.msg -recip TESTPATH/U_cms_enc_$alg_fn/cert.pem -inkey TESTPATH/U_cms_enc_$alg_fn/seckey.pem -out TESTPATH/cms_decrypt.$alg_fn" "$testname"
+#      set result [getRemoteFile "$hstname" "TESTPATH/cms_decrypt.$alg_fn" "$testname"]
+#      string eq $expected $result
+#} 0 1
+
+test "Decrypting file encrypted for $username" {
+    set expected [getFile encrypt.dat]
+    set result [openssl_remote "$username U_cms_enc_$alg_fn cms_enc_$alg_fn.msg" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_$alg_fn.msg -recip TESTPATH/U_cms_enc_$alg_fn/cert.pem -inkey TESTPATH/U_cms_enc_$alg_fn/seckey.pem" "$testname"]
+    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 cms_enc_t_$alg_fn.msg "Encrypting for $username - text format" {
+#      grep "rror" [openssl "cms -encrypt -text -in encrypt.dat -gost89 -out cms_enc_t_$alg_fn.msg U_cms_enc_$alg_fn/cert.pem"]
+#} 0 ""
+
+if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+test -createsfiles cms_decrypt_t.$alg_fn "Decrypting file text-encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       set result [openssl_remote "cms_enc_t_$alg_fn.msg U_cms_enc_$alg_fn" "$hstname" "cms -decrypt -text -in TESTPATH/cms_enc_t_$alg_fn.msg -recip TESTPATH/U_cms_enc_$alg_fn/cert.pem -inkey TESTPATH/U_cms_enc_$alg_fn/seckey.pem" "$testname"]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles cms_decrypt_t_nocert.$alg_fn "Decrypting file text-encrypted for $username without cert" {
+       set expected [getFile encrypt.dat]
+       set result [openssl_remote "cms_enc_t_$alg_fn.msg U_cms_enc_$alg_fn" "$hstname" "cms -decrypt -text -in TESTPATH/cms_enc_t_$alg_fn.msg -inkey TESTPATH/U_cms_enc_$alg_fn/seckey.pem" "$testname"]
+       string eq $expected $result
+} 0 1
+
+}
+
+
+#test -createfiles cms_enc_4all_old "Encrypt for all" {
+#      puts stdout $enc_list
+#      grep "rror" [openssl "cms -encrypt -in encrypt.dat -gost89 -out cms_enc_4all_old.msg [map {U_cms_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_cms_enc_$alg_fn
+
+if {[string length $crypt_param]} {
+       set env(CRYPT_PARAMS) $crypt_param
+} else {
+       if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+}
+
+test -createfiles cms_enc_4all_old "Encrypt for all" {
+       grep "rror" [openssl "cms -encrypt -in encrypt.dat -gost89 -out cms_enc_4all_old.msg [map {U_cms_enc_[make_fn $a]/cert.pem} $enc_list]"]
+} 0 ""
+       
+test -skip {![file exists cms_enc_4all_old.msg]} "Decrypting gost-encrypted file, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       set result [openssl_remote "cms_enc_4all_old.msg $username" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_4all_old.msg -recip TESTPATH/$username/cert.pem -inkey TESTPATH/$username/seckey.pem" "$testname"]
+       string eq $expected $result
+} 0 1
+
+test -skip {![file exists cms_enc_4all_old.msg]} -createsfiles cms_decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       set result [openssl_remote "cms_enc_4all_old.msg $username" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_4all_old.msg -inkey TESTPATH/$username/seckey.pem" "$testname"]
+       string eq $expected $result
+} 0 1
+
+}
+
+restore_env2 {OPENSSL_CONF CRYPT_PARAMS}
+}
+
+
+end_tests
diff --git a/tcl_tests/cmsenc_io.try b/tcl_tests/cmsenc_io.try
new file mode 100644 (file)
index 0000000..a78e113
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на совместимость cms и 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 {![info exist env(NO_RSA)]} {
+
+test -createsfiles io_cms_decrypt.rsa "RSA User 2 (with cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -in cms_enc_rsa.msg -recip U_cms_enc_rsa_2/cert.pem -inkey U_cms_enc_rsa_2/seckey.pem -out io_cms_decrypt.rsa"
+       set result [getFile io_cms_decrypt.rsa]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_cms_decrypt_nocert.rsa "RSA User 2 (without cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -in cms_enc_rsa.msg -inkey U_cms_enc_rsa_2/seckey.pem -out io_cms_decrypt_nocert.rsa"
+       set result [getFile io_cms_decrypt_nocert.rsa]
+       string eq $expected $result
+} 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 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:}}
+       }
+}
+
+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_cms_enc_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca ${testname}CA-2012}
+               * {set ::test::ca ${testname}CA}
+       }
+
+test -createsfiles io_cms_decrypt.$alg_fn "Decrypting file encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -in cms_enc_$alg_fn.msg -recip U_cms_enc_$alg_fn/cert.pem -inkey U_cms_enc_$alg_fn/seckey.pem -out io_cms_decrypt.$alg_fn"
+       set result [getFile io_cms_decrypt.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_cms_decrypt_t.$alg_fn "Decrypting file text-encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -text -in cms_enc_t_$alg_fn.msg -recip U_cms_enc_$alg_fn/cert.pem -inkey U_cms_enc_$alg_fn/seckey.pem -out io_cms_decrypt_t.$alg_fn"
+       set result [getFile io_cms_decrypt_t.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_cms_decrypt_t_nocert.$alg_fn "Decrypting file text-encrypted for $username without cert" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -text -in cms_enc_t_$alg_fn.msg -inkey U_cms_enc_$alg_fn/seckey.pem -out io_cms_decrypt_t_nocert.$alg_fn"
+       set result [getFile io_cms_decrypt_t_nocert.$alg_fn]
+       string eq $expected $result
+} 0 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_cms_enc_$alg_fn
+       
+test -skip {![file exists cms_enc_4all.msg]} -createsfiles io_cms_decrypt_4all.$alg_fn "Decrypting gost-encrypted file, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -in cms_enc_4all.msg -recip $username/cert.pem -inkey $username/seckey.pem -out io_cms_decrypt_4all.$alg_fn"
+       set result [getFile io_cms_decrypt_4all.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -skip {![file exists cms_enc_4all.msg]} -createsfiles io_cms_decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "smime -decrypt -in cms_enc_4all.msg -inkey $username/seckey.pem -out io_cms_decrypt_4all_nocert.$alg_fn"
+       set result [getFile io_cms_decrypt_4all_nocert.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+}
+
+end_tests
diff --git a/tcl_tests/cmsenc_sc.try b/tcl_tests/cmsenc_sc.try
new file mode 100644 (file)
index 0000000..dbd4c2b
--- /dev/null
@@ -0,0 +1,191 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+package require test
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на cms -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
+#
+
+#set ::test::ca cmsencCA-RSA
+
+#foreach user {U_cms_enc_rsa_1 U_cms_enc_rsa_2} {
+#test "Make registered user $user" {
+#      makeRegisteredUser $user rsa:512 CAname ${testname}CA-RSA
+#} 0 1
+#}
+
+#set hosts tls-ref-cp21
+#foreach hstname $hosts {
+
+#test -createsfiles cms_enc_rsa.msg "RSA User 1 encrypts message for RSA user 2" {
+#      openssl "cms -encrypt -in encrypt.dat -des -out cms_enc_rsa.msg U_cms_enc_rsa_2/cert.pem"
+#      file isfile cms_enc_rsa.msg
+#} 0 1
+
+#test "RSA User 1 cannot decrypt message for RSA user 2" {
+#      grep "Error"    [openssl_remote "cms_enc_rsa.msg U_cms_enc_rsa_1" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -recip TESTPATH/U_cms_enc_rsa_1/cert.pem -inkey TESTPATH/U_cms_enc_rsa_1/seckey.pem" "rsa"]
+#} 1 {Error decrypting CMS}
+
+#test -skip {![file exists cms_decrypt.rsa]} "RSA User 2 (with cert) can decrypt message for RSA user 2" {
+#      set expected [getFile encrypt.dat]
+#      openssl_remote "U_cms_enc_rsa_2" "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -recip TESTPATH/U_cms_enc_rsa_2/cert.pem -inkey TESTPATH/U_cms_enc_rsa_1/seckey.pem -out TESTPATH/cms_decrypt.rsa" "rsa"
+#      set result [getFile cms_decrypt.rsa]
+#      string eq $expected $result
+#} 0 1
+
+#test -skip{![file exists cms_decrypt_nocert.rsa]} "RSA User 2 (without cert) can decrypt message for RSA user 2" {
+#      set expected [getFile encrypt.dat]
+#      openssl_remote "$hstname" "cms -decrypt -in TESTPATH/cms_enc_rsa.msg -inkey TESTPATH/U_cms_enc_rsa_2/seckey.pem -out TESTPATH/cms_decrypt_nocert.rsa" "rsa"
+#      set result [getFile cms_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
+#
+
+set hosts [list tls-ref-cp21 tls-ref-cp20]
+foreach hstname $hosts {
+
+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 }}
+               "open" {set enc_list {gost2001:XA:1.2.643.2.2.31.3 gost2001:XB:1.2.643.2.2.31.4 }}
+       }
+}
+
+save_env2 {OPENSSL_CONF CRYPT_PARAMS}
+makeFile cmsenc1.cnf [regsub -all "\n\\s*CRYPT_PARAMS\\s*=\[\^\n]*" [getConfig] ""]
+set ::env(OPENSSL_CONF) [file join [pwd] cmsenc1.cnf]
+
+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_cms_enc_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca cmsencCA-2012}
+               * {set ::test::ca cmsencCA}
+       }
+
+if {[string length $crypt_param]} {
+       set env(CRYPT_PARAMS) $crypt_param
+} else {
+       if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+}
+
+test -createsfiles cms_enc_sc_$alg_fn.msg "Encrypting for $username" {
+       file mkdir 1_$hstname/$alg_fn
+       set res [open 1_$hstname/$alg_fn/cms_enc_sc_$alg_fn.msg w]
+       puts $res [openssl_remote "encrypt.dat $username $::test::ca" "$hstname" "cms -encrypt -in TESTPATH/encrypt.dat -gost89 TESTPATH/$username/cert.pem" "$testname"]
+       close $res
+} 0 ""
+
+#if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+test "Decrypting file encrypted for $username" {
+    set expected [getFile encrypt.dat]
+    set result [openssl "cms -decrypt -in 1_$hstname/$alg_fn/cms_enc_sc_$alg_fn.msg -recip $username/cert.pem -inkey $username/seckey.pem"]
+    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 cms_enc_t_$alg_fn.msg "Encrypting for $username - text format" {
+       file mkdir 2_$hstname/$alg_fn
+       set res [open 2_$hstname/$alg_fn/cms_enc_sc_t_$alg_fn.msg w]
+       puts $res [openssl_remote "encrypt.dat $username $::test::ca" "$hstname" "cms -encrypt -text -in TESTPATH/encrypt.dat -gost89 TESTPATH/$username/cert.pem" "$testname"]
+       close $res
+} 0 ""
+
+#if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+
+
+
+test "Decrypting file text-encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       set result [openssl "cms -decrypt -text -in 2_$hstname/$alg_fn/cms_enc_sc_t_$alg_fn.msg -recip $username/cert.pem -inkey $username/seckey.pem"]
+       string eq $expected $result
+} 0 1
+
+test "Decrypting file text-encrypted for $username without cert" {
+       set expected [getFile encrypt.dat]
+       set result [openssl "cms -decrypt -text -in 2_$hstname/$alg_fn/cms_enc_sc_t_$alg_fn.msg -inkey $username/seckey.pem"]
+       string eq $expected $result
+} 0 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_cms_enc_$alg_fn
+
+# Не мапится $a, потому отваливаются тесты. Выяснить, почему
+test "Encrypt for all" {
+       file mkdir 3_$hstname/$alg_fn
+       set res [open 3_$hstname/$alg_fn/cms_enc_4all_old.msg w]
+       puts $res [openssl_remote "encrypt.dat $username $::test::ca" "$hstname" "cms -encrypt -in TESTPATH/encrypt.dat -gost89 [map {TESTPATH/U_cms_enc_[make_fn $a]/cert.pem} $enc_list]" "$testname"]
+       close $res
+} 0 ""
+       
+test -skip {![file exists cms_enc_4all_old.msg]} "Decrypting gost-encrypted file, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       set result [openssl "cms -decrypt -in 3_$hstname/$alg_fn/cms_enc_4all_old.msg -recip $username/cert.pem -inkey $username/seckey.pem"]
+       string eq $expected $result
+} 0 1
+
+test -skip {![file exists cms_enc_4all_old.msg]} -createsfiles cms_decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       set result [openssl "cms -decrypt -in 3_$hstname/$alg_fn/cms_enc_4all_old.msg -inkey $username/seckey.pem"]
+       string eq $expected $result
+} 0 1
+
+}
+
+restore_env2 {OPENSSL_CONF CRYPT_PARAMS}
+}
+
+
+
+end_tests
diff --git a/tcl_tests/cmstc262019.try b/tcl_tests/cmstc262019.try
new file mode 100644 (file)
index 0000000..478298e
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/tclsh
+
+lappend auto_path [file dirname [info script]]
+package require ossltest
+file delete -force $::test::dir/tc26_cms
+file copy -force tc26_cms $::test::dir
+cd $::test::dir
+
+start_tests "CMS tests, TC26 examples"
+
+#BUILD_AT=obj_mid.l64/ ./openssl_wrap.sh cms -verify -in ../standalone-test/tc26_cms/signed_a111.pem -inform PEM -noverify
+#BUILD_AT=obj_mid.l64/ ./openssl_wrap.sh cms -verify -in ../standalone-test/tc26_cms/signed_a121.pem -inform PEM -noverify
+
+test "Signed data, 512 bits, signed attributes" {
+       grep "Verification successful" [openssl "cms -verify -in tc26_cms/signed_a111.pem -inform PEM -noverify"]
+} 0 "Verification successful
+"
+
+test "Signed data, 256 bits, no signed attributes" {
+       grep "Verification successful" [openssl "cms -verify -in tc26_cms/signed_a121.pem -inform PEM -noverify"]
+} 0 "Verification successful
+"
+
+test "Digested data, 256 bits" {
+       grep "Verification successful" [openssl "cms -digest_verify -in tc26_cms/hashed_a311.pem -inform PEM -out hashed_a311.out"]
+} 0 "Verification successful
+"
+
+test "Digested data, 512 bits" {
+       grep "Verification successful" [openssl "cms -digest_verify -in tc26_cms/hashed_a321.pem -inform PEM -out hashed_a321.out"]
+} 0 "Verification successful
+"
+
+end_tests
diff --git a/tcl_tests/cnt0.enc b/tcl_tests/cnt0.enc
new file mode 100644 (file)
index 0000000..a9dd2d2
--- /dev/null
@@ -0,0 +1 @@
+Salted__h§®\9b\v5UÏ\eå,\13\9e~j³\88D±¤\ fug¼]\1e\17_'
\ No newline at end of file
diff --git a/tcl_tests/cnt1.enc b/tcl_tests/cnt1.enc
new file mode 100644 (file)
index 0000000..71551f3
--- /dev/null
@@ -0,0 +1 @@
+\eå,\13\9e~j³\88D±¤\ fug¼]\1e\17_'
\ No newline at end of file
diff --git a/tcl_tests/cp10.ciphers b/tcl_tests/cp10.ciphers
new file mode 100644 (file)
index 0000000..7e4fe75
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# óÔÒÕËÔÕÒÁ ÆÁÊÌÁ
+# ÁÌÇÏÒÉÔÍ {
+# ciphersuite host:port[:servertype]
+# ciphersuite host:port
+#
+# }
+# Where servertype can be apache (default) or iis.
+
+#gost94:XA {
+#      GOST94-GOST89-GOST89 tls-ref-cp10.lan.cryptocom.ru:4403
+#      GOST94-NULL-GOST94 tls-ref-cp10.lan.cryptocom.ru:4404
+#}     
+
+gost2001:XA {
+       GOST2001-GOST89-GOST89 tls-ref-cp10.lan.cryptocom.ru:443
+       GOST2001-NULL-GOST94 tls-ref-cp10.lan.cryptocom.ru:4401
+}
+rsa:1024 {
+       DHE-RSA-AES256-SHA tls-ref-cp10.lan.cryptocom.ru:4407
+       RC4-SHA tls-ref-cp10.lan.cryptocom.ru:4408
+}
diff --git a/tcl_tests/cp20.ciphers b/tcl_tests/cp20.ciphers
new file mode 100644 (file)
index 0000000..2b4bf78
--- /dev/null
@@ -0,0 +1,8 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 tls-ref-cp20.lan.cryptocom.ru:443
+       GOST2001-NULL-GOST94 tls-ref-cp20.lan.cryptocom.ru:4401
+}
+rsa:1024 {
+       DHE-RSA-AES256-SHA tls-ref-cp20.lan.cryptocom.ru:4407
+       RC4-SHA tls-ref-cp20.lan.cryptocom.ru:4408
+}
diff --git a/tcl_tests/cp21.ciphers b/tcl_tests/cp21.ciphers
new file mode 100644 (file)
index 0000000..914c2d1
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# óÔÒÕËÔÕÒÁ ÆÁÊÌÁ
+# ÁÌÇÏÒÉÔÍ {
+# ciphersuite host:port[:servertype]
+# ciphersuite host:port
+#
+# }
+# Where servertype can be apache (default) or iis.
+
+gost2001:XA {
+       TLSv1:GOST2001-GOST89-GOST89 tls-ref-cp21.lan.cryptocom.ru:443
+       TLSv1:GOST2001-NULL-GOST94 tls-ref-cp21.lan.cryptocom.ru:4401
+}
+rsa:1024 {
+       TLSv1.2:DHE-RSA-AES256-SHA tls-ref-cp21.lan.cryptocom.ru:4407
+       TLSv1.2:RC4-SHA tls-ref-cp21.lan.cryptocom.ru:4408
+}
diff --git a/tcl_tests/csp3.ciphers b/tcl_tests/csp3.ciphers
new file mode 100644 (file)
index 0000000..77d2837
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp3-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp36.ciphers b/tcl_tests/csp36.ciphers
new file mode 100644 (file)
index 0000000..a791e00
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp36-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp36r2.ciphers b/tcl_tests/csp36r2.ciphers
new file mode 100644 (file)
index 0000000..a187bfa
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp36r2-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp36r3.ciphers b/tcl_tests/csp36r3.ciphers
new file mode 100644 (file)
index 0000000..8ea8cd5
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp36r3-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp36r4.ciphers b/tcl_tests/csp36r4.ciphers
new file mode 100644 (file)
index 0000000..2ef5496
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp36r4-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp39.ciphers b/tcl_tests/csp39.ciphers
new file mode 100644 (file)
index 0000000..82bd0ba
--- /dev/null
@@ -0,0 +1,4 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp39-srv.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/csp4.ciphers b/tcl_tests/csp4.ciphers
new file mode 100644 (file)
index 0000000..55b5e8f
--- /dev/null
@@ -0,0 +1,10 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp4-01.vm.cryptocom.ru:443:iis
+       GOST2012-GOST8912-GOST8912 v-cp4-01.vm.cryptocom.ru:443:iis
+}
+gost2012_256:XA {
+       GOST2012-GOST8912-GOST8912 v-cp4-12S.vm.cryptocom.ru:443:iis
+}
+gost2012_512:A {
+       GOST2012-GOST8912-GOST8912 v-cp4-12L.vm.cryptocom.ru:443:iis
+}
diff --git a/tcl_tests/csp4r2.ciphers b/tcl_tests/csp4r2.ciphers
new file mode 100644 (file)
index 0000000..44eb401
--- /dev/null
@@ -0,0 +1,10 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp4r2-01.vm.cryptocom.ru:443:iis
+       GOST2012-GOST8912-GOST8912 v-cp4r2-01.vm.cryptocom.ru:443:iis
+}
+gost2012_256:XA {
+       GOST2012-GOST8912-GOST8912 v-cp4r2-12S.vm.cryptocom.ru:443:iis
+}
+gost2012_512:A {
+       GOST2012-GOST8912-GOST8912 v-cp4r2-12L.vm.cryptocom.ru:443:iis
+}
diff --git a/tcl_tests/csp4r3.ciphers b/tcl_tests/csp4r3.ciphers
new file mode 100644 (file)
index 0000000..acedd4f
--- /dev/null
@@ -0,0 +1,14 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp4r3-01.vm.cryptocom.ru:443:iis
+       GOST2012-GOST8912-GOST8912 v-cp4r3-01.vm.cryptocom.ru:443:iis
+}
+gost2012_256:XA {
+       TLSv1:GOST2012-GOST8912-GOST8912 v-cp4r3-12S.vm.cryptocom.ru:443:iis
+       TLSv1.1:GOST2012-GOST8912-GOST8912 v-cp4r3-12S.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-GOST8912-GOST8912 v-cp4r3-12S.vm.cryptocom.ru:443:iis
+}
+gost2012_512:A {
+       TLSv1:GOST2012-GOST8912-GOST8912 v-cp4r3-12L.vm.cryptocom.ru:443:iis
+       TLSv1.1:GOST2012-GOST8912-GOST8912 v-cp4r3-12L.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-GOST8912-GOST8912 v-cp4r3-12L.vm.cryptocom.ru:443:iis
+}
diff --git a/tcl_tests/csp5.ciphers b/tcl_tests/csp5.ciphers
new file mode 100644 (file)
index 0000000..e8c1a45
--- /dev/null
@@ -0,0 +1,18 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-cp5-01.vm.cryptocom.ru:443:iis
+       GOST2012-GOST8912-GOST8912 v-cp5-01.vm.cryptocom.ru:443:iis
+}
+gost2012_256:XA {
+       TLSv1:GOST2012-GOST8912-GOST8912 v-cp5-12S.vm.cryptocom.ru:443:iis
+       TLSv1.1:GOST2012-GOST8912-GOST8912 v-cp5-12S.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-GOST8912-GOST8912 v-cp5-12S.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-KUZNYECHIK-KUZNYECHIKOMAC v-cp5-12S.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-MAGMA-MAGMAOMAC v-cp5-12S.vm.cryptocom.ru:443:iis
+}
+gost2012_512:A {
+       TLSv1:GOST2012-GOST8912-GOST8912 v-cp5-12L.vm.cryptocom.ru:443:iis
+       TLSv1.1:GOST2012-GOST8912-GOST8912 v-cp5-12L.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-GOST8912-GOST8912 v-cp5-12L.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-KUZNYECHIK-KUZNYECHIKOMAC v-cp5-12L.vm.cryptocom.ru:443:iis
+       TLSv1.2:GOST2012-MAGMA-MAGMAOMAC v-cp5-12L.vm.cryptocom.ru:443:iis
+}
diff --git a/tcl_tests/dgst.try b/tcl_tests/dgst.try
new file mode 100644 (file)
index 0000000..148e1d6
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду dgst"
+
+switch -exact [engine_name] {
+       "ccore" {set signalg { gost2001:A gost2012_256:A gost2012_512:A}}
+       "open" {set signalg { gost2001:A gost2012_256:A gost2012_512:A}}
+}
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       set alg_list $signalg
+}
+
+set hash_alg_list { md5 hash_94 hash_12_256 hash_12_512 }
+
+# ===============
+# GOST 34.11-2012
+# ===============
+
+test -createsfiles {dgst.dat dgst0.dat dgst2.dat dgst8.dat dgst63.dat dgst_CF.dat} "Формирование тестовых данных" {
+       makeFile dgst.dat [string repeat "Test data to digest.\n" 100] binary
+       makeFile dgst0.dat "" binary
+       makeFile dgst63.dat "012345678901234567890123456789012345678901234567890123456789012" binary
+       file copy -force ../dgst_CF.dat ../dgst_ex1.dat ../dgst_ex2.dat .
+} 0 ""
+
+test "Вычисление дайджеста алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst63.dat"]
+} 0 "md_gost12_256\(dgst63.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\n"
+
+test "Два дайджеста алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst63.dat dgst63.dat"]
+} 0 "md_gost12_256\(dgst63.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\nmd_gost12_256\(dgst63.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\n" 
+
+test "Дайджест от данных нулевой длины алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst0.dat"]
+} 0 "md_gost12_256\(dgst0.dat)= 3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb\n"
+
+test "Дайджест от спец.данных алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst_CF.dat"]
+} 0 "md_gost12_256\(dgst_CF.dat)= 81bb632fa31fcc38b4c379a662dbc58b9bed83f50d3a1b2ce7271ab02d25babb\n"
+
+test "Дайджест от контрольного примера 1 алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst_ex1.dat"]
+} 0 "md_gost12_256\(dgst_ex1.dat)= 9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500\n"
+
+test "Дайджест от контрольного примера 2 алгоритмом md_gost12_256" {
+       grep "md_gost12_256\\(" [openssl "dgst -md_gost12_256 dgst_ex2.dat"]
+} 0 "md_gost12_256\(dgst_ex2.dat)= 9dd2fe4e90409e5da87f53976d7405b0c0cac628fc669a741d50063c557e8f50\n"
+
+test "Вычисление дайджеста алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst63.dat"]
+} 0 "md_gost12_512\(dgst63.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\n"
+
+test "Два дайджеста алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst63.dat dgst63.dat"]
+} 0 "md_gost12_512\(dgst63.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\nmd_gost12_512\(dgst63.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\n" 
+
+test "Дайджест от данных нулевой длины алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst0.dat"]
+} 0 "md_gost12_512\(dgst0.dat)= 8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a\n"
+
+test "Дайджест от спец.данных алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst_CF.dat"]
+} 0 "md_gost12_512\(dgst_CF.dat)= 8b06f41e59907d9636e892caf5942fcdfb71fa31169a5e70f0edb873664df41c2cce6e06dc6755d15a61cdeb92bd607cc4aaca6732bf3568a23a210dd520fd41\n"
+
+test "Дайджест от контрольного примера 1 алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst_ex1.dat"]
+} 0 "md_gost12_512\(dgst_ex1.dat)= 1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48\n"
+
+test "Дайджест от контрольного примера 2 алгоритмом md_gost12_512" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 dgst_ex2.dat"]
+} 0 "md_gost12_512\(dgst_ex2.dat)= 1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28\n"
+
+test "Вычисление дайджеста алгоритмом md_gost94" {
+       grep "md_gost94\\(" [openssl "dgst -md_gost94 dgst.dat"]
+} 0 "md_gost94\(dgst.dat)= 42e462ce1c2b4bf72a4815b7b4877c601f05e5781a71eaa36f63f836c021865c\n"
+
+test  "Вычисление двух дайджестов алгоритмом md_gost94" {
+       grep "md_gost94\\(" [openssl "dgst -md_gost94 dgst.dat dgst.dat"]
+} 0 "md_gost94\(dgst.dat)= 42e462ce1c2b4bf72a4815b7b4877c601f05e5781a71eaa36f63f836c021865c\nmd_gost94\(dgst.dat)= 42e462ce1c2b4bf72a4815b7b4877c601f05e5781a71eaa36f63f836c021865c\n" 
+
+test "Вычисление дайджеста от данных нулевой длины алгоритмом md_gost94" {
+       grep "md_gost94\\(" [openssl "dgst -md_gost94 dgst0.dat"]
+} 0 "md_gost94\(dgst0.dat)= 3f25bc1fbbce27ca10fb1958f319473ae7e17482c3b53ecf47a7e2de8aabe4c8\n"
+
+
+foreach alg $alg_list {
+  set alg_fn [string map {":" "_"} $alg]
+  set username dgst_$alg_fn
+
+  test -createsfiles $username/seckey.pem "Секретный ключ, алгоритм $alg" {
+    makeSecretKey $username $alg
+  } 0 1
+
+
+  foreach hash_alg $hash_alg_list {
+
+    if { ($alg eq "rsa:") || ($hash_alg eq [alg_hash $alg]) } {
+
+      test -skip {![file exists $username/seckey.pem]||![file exists dgst.dat]} -createsfiles $username/sig.bin  "Подпись дайджеста $hash_alg алгоритмом $alg" {
+        openssl "dgst -[hash_short_name $hash_alg] -sign $username/seckey.pem -out $username/sig.bin dgst.dat"
+        expr {[file size $username/sig.bin] > 0}
+      } 0 1
+
+      test -skip {![file exists $username/seckey.pem]||![file exists $username/sig.bin]} "Проверка подписи под дайджестом $hash_alg на алгоритме $alg" {
+        grep Verif [openssl "dgst -[hash_short_name $hash_alg] -prverify $username/seckey.pem -signature $username/sig.bin dgst.dat"]  
+      } 0 "Verified OK
+"
+
+    } else {
+      test -skip {![file exists $username/seckey.pem]||![file exists dgst.dat]} -createsfiles "testmd5.bin"  "Подпись несовместимого дайджеста $hash_alg c подписью $alg" {
+        grep Error [openssl "dgst -[hash_short_name $hash_alg] -sign $username/seckey.pem -out testmd5.bin dgst.dat"]
+      } 1 {invalid digest type}
+    }
+
+  }
+
+}
+
+end_tests
diff --git a/tcl_tests/dgst_CF.dat b/tcl_tests/dgst_CF.dat
new file mode 100644 (file)
index 0000000..a6c1240
--- /dev/null
@@ -0,0 +1 @@
+îîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîî\16\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\16
\ No newline at end of file
diff --git a/tcl_tests/dgst_ex1.dat b/tcl_tests/dgst_ex1.dat
new file mode 100644 (file)
index 0000000..f2316d6
--- /dev/null
@@ -0,0 +1 @@
+012345678901234567890123456789012345678901234567890123456789012
\ No newline at end of file
diff --git a/tcl_tests/dgst_ex2.dat b/tcl_tests/dgst_ex2.dat
new file mode 100644 (file)
index 0000000..57f9b3f
--- /dev/null
@@ -0,0 +1 @@
+Ñå âåòðè, Ñòðèáîæè âíóöè, âåþòú ñ ìîðÿ ñòðåëàìè íà õðàáðûÿ ïëúêû Èãîðåâû
\ No newline at end of file
diff --git a/tcl_tests/enc.try b/tcl_tests/enc.try
new file mode 100644 (file)
index 0000000..2f682a7
--- /dev/null
@@ -0,0 +1,222 @@
+#!/usr/bin/tclsh/
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]] 
+package require ossltest
+set plain0 [getFile plain.enc]
+file copy -force cfb0.enc $::test::dir
+file copy -force cnt0.enc $::test::dir
+file copy -force cbc0.enc $::test::dir
+file copy -force aes0.enc $::test::dir
+file copy -force plain.enc $::test::dir
+file copy -force magma_plain.enc $::test::dir
+file copy -force magma_acpkm_plain.enc $::test::dir
+set cfb1 [getFile cfb1.enc]
+set cbc1 [getFile cbc1.enc]
+set cnt1 [getFile cnt1.enc]
+set aes1 [getFile aes1.enc]
+set magma1 [getFile magma1.enc]
+set macpkm1 [getFile macpkm1.enc]
+cd $::test::dir 
+file delete cfb1.enc cbc1.enc cnt1.enc aes1.enc magma1.enc magma1.enc macpkm1.enc
+start_tests "Тесты на команду enc" 
+
+save_env2 {CRYPT_PARAMS}
+if [info exists env(CRYPT_PARAMS)] {unset env(CRYPT_PARAMS)}
+
+test -createsfiles cfb0.dec "Decrypting etalon file in CFB mode" {
+       openssl "enc -gost89 -d -md md5 -in cfb0.enc -out cfb0.dec -k 1234567890 -p"
+       getFile cfb0.dec 
+} 0 $plain0
+
+test -createsfiles cnt0.dec "Decrypting etalon file CNT mode" {
+       openssl "enc -gost89-cnt -d -md md5 -in cnt0.enc -out cnt0.dec -k 1234567890 -p"
+       getFile cnt0.dec 
+} 0 $plain0
+
+test -createsfiles cbc0.dec "Decrypting etalon file in CBC mode" {
+       openssl "enc -gost89-cbc -d -md md5 -in cbc0.enc -out cbc0.dec -k 1234567890 -p"
+       getFile cbc0.dec 
+} 0 $plain0
+
+test -createsfiles aes0.dec "Decrypting etalon file encrypted with AES" {
+       openssl "enc -aes-128-cbc -d -md md5 -in aes0.enc -out aes0.dec -k 1234567890"
+       getFile aes0.dec 
+} 0 $plain0
+
+
+test -createsfiles cfb1.enc "Encrypting etalon file in CFB mode" {
+       openssl "enc -gost89 -in plain.enc -out cfb1.enc -K 0D6F24152DB4B18CC4B0EE62F55FAD0BEADC26E7992C5EDF039114EC3F44EB08 -iv 8EE68900818CD1F9 -p"
+       getFile cfb1.enc 
+} 0 $cfb1
+
+test -createsfiles cnt1.enc "Encrypting etalon file in CNT mode" {
+       openssl "enc -gost89-cnt -in plain.enc -out cnt1.enc -K EF164FDF5B1128DE44AFCC00A0323DC1090EC99DE9C6B085B0D2550AB9F1AF47 -iv 9AF32B4E2FB1DF3D -p"
+       getFile cnt1.enc 
+} 0 $cnt1
+
+test -createsfiles cbc1.enc "Encrypting etalon file in CBC mode" {
+       openssl "enc -gost89-cbc -in plain.enc -out cbc1.enc -K F6AF8D0EDF555D164E3DDFA20615D7DF602B99A5ED4BD4103C4CA622D4544636 -iv 8264BBB5A072CDB5 -p"
+       getFile cbc1.enc 
+} 0 $cbc1
+
+test -createsfiles aes1.enc "Encrypting etalon file with AES" {
+       openssl "enc -aes-128-cbc -in plain.enc -out aes1.enc -K D45358C3C6E711392E9F2AFF46C444B1 -iv 78E88EFC8F44B9C27C45C5FCC61DCD94 -p"
+       getFile aes1.enc 
+} 0 $aes1
+
+
+set plain "Test data to encrypt "
+makeFile enc.dat $plain binary
+set plain2 [string repeat "Test data for encrypt of big string\n" 64]
+makeFile enc2.dat $plain2 binary
+
+test -createsfiles {cfb.enc} "Encrypting file in CFB mode" {
+       openssl "enc -gost89 -out cfb.enc -in enc.dat -k 1234567890 -p"
+       file isfile cfb.enc
+} 0 1
+
+test -createsfiles {cnt.enc} "Encrypting file in CNT mode" {
+       openssl "enc -gost89-cnt -out cnt.enc -in enc.dat -k 1234567890 -p"
+       file isfile cnt.enc
+} 0 1
+
+test -createsfiles {cbc.enc} "Encrypting file in CBC mode" {
+       openssl "enc -gost89-cbc -out cbc.enc -in enc.dat -k 1234567890 -p"
+       file isfile cbc.enc
+} 0 1
+
+test -createsfiles aes.enc "Encrypting file using aes" {
+       openssl "enc -aes-128-cbc -out aes.enc -in enc.dat -k 1234567890"
+       file isfile aes.enc     
+} 0 1
+
+test "Ciphered text in CFB mode  differs from plain text" {
+       set ciphered [getFile cfb.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test "Ciphered text in CNT mode  differs from plain text" {
+       set ciphered [getFile cnt.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test "Ciphered text in CBC mode  differs from plain text" {
+       set ciphered [getFile cbc.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test "Ciphered with aes text differs from plain text" {
+       set ciphered [getFile aes.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test -createsfiles cfb.dec "Decrypting file, encrypted in CFB mode" {
+       openssl "enc -gost89 -d -in cfb.enc -out enc.dec -k 1234567890 -p"
+       getFile enc.dec 
+} 0 $plain
+
+test -createsfiles cnt.dec "Decrypting file, encrypted in CNT mode" {
+       openssl "enc -gost89-cnt -d -in cnt.enc -out cnt.dec -k 1234567890 -p"
+       getFile cnt.dec 
+} 0 $plain
+
+test -createsfiles cbc.dec "Decrypting file, encrypted in CBC mode" {
+       openssl "enc -gost89-cbc -d -in cbc.enc -out cbc.dec -k 1234567890 -p"
+       getFile cbc.dec 
+} 0 $plain
+
+test -createsfiles aes.dec "Decrypting file encrypted with aes" {
+       openssl "enc -aes-128-cbc -d -in aes.enc -out aes.dec -k 1234567890"
+       getFile aes.dec 
+} 0 $plain
+
+
+test -createsfiles {cfb2.enc} "Encrypting more than 1KB" {
+       if [info exists env(CRYPT_PARAMS)] {unset env(CRYPT_PARAMS)}
+       openssl "enc -gost89 -out cfb2.enc -in enc2.dat -k 1234567890 -p"
+       file isfile cfb2.enc
+} 0 1
+
+test -createsfiles {cfb2.dec} "Decrypting more than 1Kb" {
+       openssl "enc -d -gost89 -out cfb2.dec -in cfb2.enc -k 1234567890 -p"
+       getFile cfb2.dec
+} 0 $plain2    
+
+test -createsfiles {cnt2.enc} "Encrypting more than 1KB in CNT mode" {
+       if [info exists env(CRYPT_PARAMS)] {unset env(CRYPT_PARAMS)}
+       openssl "enc -gost89-cnt -out cnt2.enc -in enc2.dat -k 1234567890 -p"
+       file isfile cnt2.enc
+} 0 1
+
+test -createsfiles {cnt2.dec} "Decrypting more than 1Kb in CNT mode" {
+       openssl "enc -d -gost89-cnt -out cnt2.dec -in cnt2.enc -k 1234567890 -p"
+       getFile cnt2.dec
+} 0 $plain2    
+
+test -createsfiles {cnc2.enc} "Encrypting more than 1KB in CBC mode" {
+       if [info exists env(CRYPT_PARAMS)] {unset env(CRYPT_PARAMS)}
+       openssl "enc -gost89-cbc -out cbc2.enc -in enc2.dat -k 1234567890 -p"
+       file isfile cbc2.enc
+} 0 1
+
+test -createsfiles {cbc2.dec} "Decrypting more than 1Kb in CBC mode" {
+       openssl "enc -d -gost89-cbc -out cbc2.dec -in cbc2.enc -k 1234567890 -p"
+       getFile cbc2.dec
+} 0 $plain2    
+
+test -skip {![file exists enc2.dat]} -createsfiles {cfb3.enc} "Encrypting with paramset TC26 (symbolic)" {
+       set env(CRYPT_PARAMS) "id-tc26-gost-28147-param-Z"
+       openssl "enc -gost89 -out cfb3.enc -in enc2.dat -k 1234567890 -p"
+       file isfile cfb3.enc
+} 0 1
+
+test -skip {![file exists cfb3.enc]} -createsfiles {cfb3.dec1} "Decrypting with paramset TC26 (OID)" {
+       set env(CRYPT_PARAMS) "1.2.643.7.1.2.5.1.1"
+       openssl "enc -gost89 -d -in cfb3.enc -out cfb3.dec1 -k 1234567890 -p"
+       getFile cfb3.dec1       
+} 0 $plain2
+
+test -skip {![file exists enc2.dat]} -createsfiles {cbc3.enc} "Encrypting in CBC mode with paramset RIC 1 (symbolic)" {
+       set env(CRYPT_PARAMS) "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+       openssl "enc -gost89-cbc -out cbc3.enc -in enc2.dat -k 1234567890 -p"
+       file isfile cbc3.enc
+} 0 1
+
+test -skip {![file exists cbc3.enc]} -createsfiles {cbc3.dec1} "Decrypting in CBC mode with paramset RIC 1 (OID)" {
+       set env(CRYPT_PARAMS) "1.2.643.2.2.31.7"
+       openssl "enc -gost89-cbc -d -in cbc3.enc -out cbc3.dec1 -k 1234567890 -p"
+       getFile cbc3.dec1       
+} 0 $plain2
+restore_env2 {CRYPT_PARAMS}
+
+save_env2 {CRYPT_PARAMS OPENSSL_CONF}
+test -skip {![file exists cfb3.enc]} -createsfiles {cfb3.dec2} "Decrypting with default params" {
+       if [info exists env(CRYPT_PARAMS)] {unset env(CRYPT_PARAMS)}
+       makeFile enc1.cnf [regsub -all "\n\\s*CRYPT_PARAMS\\s*=\[\^\n]*" [getConfig] ""]
+       set ::env(OPENSSL_CONF) [file join [pwd] enc1.cnf]
+       openssl "enc -gost89 -d -in cfb3.enc -out cfb3.dec2 -k 1234567890 -p"
+       getFile cfb3.dec2       
+} 0 $plain2
+restore_env2 {CRYPT_PARAMS OPENSSL_CONF}
+
+save_env2 {CRYPT_PARAMS}
+test -skip {![file exists cfb3.enc]} -createsfiles {cfb3.dec3} "Decrypting with  wrong explicitely set" {
+       set env(CRYPT_PARAMS) "id-Gost28147-89-CryptoPro-B-ParamSet"
+       openssl "enc -gost89 -d -in cfb3.enc -out cfb3.dec3 -k 1234567890 -p"
+       string equal [getFile cfb3.dec3] $plain2        
+} 0 0
+
+restore_env2 {CRYPT_PARAMS}
+
+test -createsfiles magma1.enc "Encrypting etalon file (Magma-CTR)" {
+       openssl "enc -magma-ctr -K ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -iv 1234567800000000 -in magma_plain.enc -out magma1.enc"
+       getFile magma1.enc 
+} 0 $magma1
+
+test -createsfiles macpkm1.enc "Encrypting etalon file (Magma-ACPKM)" {
+       openssl "enc -id-tc26-cipher-gostr3412-2015-magma-ctracpkm -K F797256845F36CF075603445CD322BACC3834032BC425E4D3C8495236F7B6CAF -iv 00000FFF00000000 -in magma_acpkm_plain.enc -out macpkm1.enc"
+       getFile macpkm1.enc 
+} 0 $macpkm1
+
+
+end_tests
diff --git a/tcl_tests/engine.try b/tcl_tests/engine.try
new file mode 100644 (file)
index 0000000..2090e59
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir 
+start_tests "Тесты на команду engine" 
+
+switch -exact [engine_name] {
+       "ccore" {set list " \[RAND, gost89, gost89-cnt, gost89-cnt-12, gost89-cbc, id-tc26-cipher-gostr3412-2015-magma-ctracpkm, magma-ctr, magma-ofb, magma-cbc, magma-cfb, grasshopper-ecb, grasshopper-cbc, grasshopper-ofb, grasshopper-cfb, grasshopper-ctr, id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm, md_gost94, gost-mac, md_gost12_256, md_gost12_512, gost-mac-12, gost2001, id-GostR3410-2001DH, gost-mac, gost2012_256, gost2012_512, gost-mac-12\]\n"}
+       "open" {set list "(gost) Reference implementation of GOST engine\n \[gost89, gost89-cnt, gost89-cnt-12, gost89-cbc, md_gost94, gost-mac, md_gost12_256, md_gost12_512, gost-mac-12, gost2001, gost-mac, gost2012_256, gost2012_512, gost-mac-12\]\n"}
+}
+
+
+makeFile no_engine.cnf [regsub -all "\n\\s*engines\\s*=\\s*engines_section\[\^\n]*" [getConfig] ""]
+
+save_env2 {OPENSSL_CONF}
+set env(OPENSSL_CONF) [file join [pwd] no_engine.cnf]
+
+test "Проверяем поддержку российских алгоритмов" {
+       grep "gost" [openssl "engine -c $env(ENGINE_NAME)"]
+} 0 $list
+
+if {[engine_name] == "ccore"} {
+test "Получение списка конфигурационных параметров" {
+       openssl "engine -v cryptocom"
+} 0 "(cryptocom) Cryptocom GOST engine
+     RNG, RNG_PARAMS, CRYPT_PARAMS, CCENGINE_LICENSE, GOST_PBE_HMAC
+"
+}
+
+restore_env2 {OPENSSL_CONF}
+
+end_tests
diff --git a/tcl_tests/enums.tcl b/tcl_tests/enums.tcl
new file mode 100644 (file)
index 0000000..2709286
--- /dev/null
@@ -0,0 +1,23 @@
+set f [open enums2tcl.c w]
+puts $f "#include \"../ccore/ccapi.h\""
+puts $f "#include \"../ccore/ccrdscb.h\""
+puts $f "#include <stdio.h>"
+puts $f "int main (void) {"
+set inc [open ../ccore/ccapi.h r]
+while {[gets $inc line] >= 0} {
+       if [regexp {\bcc_rc_\w+} $line code] {
+               puts $f "printf(\"set $code %d\\n\", $code);"
+       }
+}
+close $inc
+set inc [open ../ccore/ccrdscb.h r]
+while {[gets $inc line] >= 0} {
+       if [regexp {\bcc_rds_cb_(rc|op|stage)_\w+} $line code] {
+               puts $f "printf(\"set $code %d\\n\", $code);"
+       }
+}
+close $inc
+puts $f "return 0;"
+puts $f "}"
+close $f
+
diff --git a/tcl_tests/getengine.tcl b/tcl_tests/getengine.tcl
new file mode 100644 (file)
index 0000000..49176c0
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/tclsh
+lappend auto_path .
+package require ossltest
+
+proc getConfigLine {var {section ""}} {
+   global config
+   if {[string length $section]} {
+               if {[regexp -indices "\n\\s*\\\[\\s*$section\\s*\\\]\\s*\n" $config start]} {
+                       set start [lindex $start 1]
+               } else {
+                       return -code error "Section $section is not found"
+               }       
+       } else {
+               set start 0
+       }
+       if {[regexp -indices "\n\\s*\\\[\[^\n\]+\\\]\\s*\n" [string range $config $start end] end]} {
+               set end [expr $start+[lindex $end 0]]
+       } else {
+               set end end
+       }
+       if {![regexp "\n\\s*$var\\s*=\\s*(\\S\[^\n\]+?)\\s*\n" "\n[string range $config $start $end]" => value]} {
+               return -code error "No variable $var in section $section"
+       }       
+       return $value
+}
+
+set config [getConfig] 
+
+set openssl_def [getConfigLine openssl_conf]
+
+set engine_section [getConfigLine {[^#]+}  [getConfigLine engines $openssl_def ]]
+
+puts [getConfigLine engine_id $engine_section]
+
+
+
+
diff --git a/tcl_tests/http.tcl b/tcl_tests/http.tcl
new file mode 100644 (file)
index 0000000..6121617
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- coding: cp1251 -*-
+# 
+# Получает в командной строке URL и (опционально) строку для поиска
+# сертификата. Выполняет HTTP-запрос и возрвщает результат
+# В строке для поиска сертификата можно использовать прямые слэши вместо
+# обратных.
+
+if {!$argc || $argc>2} {
+       puts stderr "Usage $argv0 url \[cert-spec\]"
+}      
+
+set url [lindex $argv 0]
+if {$argc==2} {
+       set certspec [string map {/ \\} [lindex $argv 1]]
+}      
+
+
+puts Started
+
+package require tcom
+set hh [::tcom::ref createobject WinHttp.WinHttpRequest.5.1]
+$hh Open GET $url 0
+if {[info exists certspec]} {
+       puts "Setting Client Certificate $certspec"
+       $hh SetClientCertificate $certspec
+}
+$hh Send
+puts [$hh ResponseText]
diff --git a/tcl_tests/hwkeys.tcl b/tcl_tests/hwkeys.tcl
new file mode 100644 (file)
index 0000000..8c86a82
--- /dev/null
@@ -0,0 +1,229 @@
+# -*- coding: cp1251 -*-
+package require testlib
+
+start_tests "Работа с аппаратными носителями"
+
+if [info exists ::env(BASE_OPENSSL_CONF)] {
+       set openssl_cnf [myfile openssl.cnf]
+       set bf [open $::env(BASE_OPENSSL_CONF) r]
+       set f [open $openssl_cnf w]
+       set engines {}
+       set in_engines 0
+       while {[gets $bf line] >= 0} {
+               puts $f $line
+               if {[regexp {^\[engine_section\]} $line]} {
+                       puts $f "ce_filecnt_keys = cefk_section"
+               }
+       }
+       close $bf
+       if {$tcl_platform(platform) eq "windows"} {
+               set lib_prefix  ""
+               set lib_suffix ".dll"
+       } else {
+               set lib_prefix "lib"
+               set lib_suffix ".so"
+       }       
+       puts $f "\[cefk_section\]       
+dynamic_path = \$ENV::TEST_ENGINE_DIR/${lib_prefix}ce_filecnt_keys$lib_suffix
+engine_id = ce_filecnt_keys
+default_algorithms = ALL
+\[req\]
+prompt=no
+distinguished_name = req_dn
+\[ req_dn \]
+OU=OpenSSL Team
+L=Moscow
+CN=Dummy user
+emailAddress=openssl@cryptocom.ru
+O=Cryptocom
+C=RU"
+       close $f
+       file copy  [file dirname $env(BASE_OPENSSL_CONF)]/cryptocom.lic [file dirname $openssl_cnf]/cryptocom.lic
+       set ::env(OPENSSL_CONF) $openssl_cnf
+       puts [logchannel] "OPENSSL_CONF=$::env(OPENSSL_CONF)"
+       set ::env(TEST_ENGINE_DIR) [regsub {(/[^/]+)$} $::env(ENGINE_DIR) {/t\1}]
+       puts [logchannel] "TEST_ENGINE_DIR=$::env(TEST_ENGINE_DIR)"
+}
+
+set cnt_pln_file [myfile cnt_pln]
+set cnt_pln_dot_file [myfile cnt.pln.S]
+set cnt_pln FILECNT=$cnt_pln_file
+set cnt_enc_file [myfile cnt_enc]
+set cnt_enc FILECNT=$cnt_enc_file
+file copy -force ../cnt.pln $cnt_pln_file
+file copy -force ../cnt.pln $cnt_pln_dot_file
+file copy -force ../cnt.pln default_file_container
+file copy -force ../cnt.enc $cnt_enc_file
+set cntname "test keys"
+
+file delete $cnt_enc_file.cmd $cnt_pln_file.cmd
+eval [exec enums2tcl]
+
+foreach K {S X} {
+       set cert$K [myfile cert$K.pem]
+       set pubk$K [myfile pubk$K.pem]
+       upvar 0 cert$K cert pubk$K pubk
+
+       test -title "$K: сертификат и его открытый ключ" -id cert$K {
+               run openssl req -new -x509 -key $cnt_pln.$K -keyform ENGINE -engine cryptocom -out $cert
+               run openssl x509 -pubkey -noout -in $cert
+               file rename _stdout $pubk
+       }
+
+       test -title "$K: Подписываем файл закрытым ключом" -id sign$K -dep cert$K {
+               run openssl dgst -md_gost94 -sign $cnt_pln.$K -keyform ENGINE -engine cryptocom -out $cert.sig $cert
+       }
+
+       test -title "$K: Проверяем подпись на закрытом ключе" -dep sign$K {
+               run openssl dgst -md_gost94 -prverify $cnt_pln.$K -keyform ENGINE -engine cryptocom -signature $cert.sig $cert
+       }
+
+       test -title "$K: Проверяем подпись на открытом ключе" -dep sign$K {
+               run openssl dgst -md_gost94 -verify $pubk -signature $cert.sig $cert
+       }
+
+       test -title "$K: Подписываем файл закрытым ключом, контейнер с именем" -id sign$K -dep cert$K {
+               run openssl dgst -md_gost94 -sign $cnt_pln:$cntname.$K -keyform ENGINE -engine cryptocom -out $cert.sig $cert
+       }
+
+       test -title "$K: Подписываем файл запароленным закрытым ключом" -dep cert$K {
+               run openssl dgst -md_gost94 -sign $cnt_enc.$K -keyform ENGINE -engine cryptocom -out $cert.sig -passin pass:abcdefghijklmnopqrstuvwxyz1234567890 $cert
+               run openssl dgst -md_gost94 -verify $pubk -signature $cert.sig $cert
+       }
+
+}
+
+test -title "Читаем по полной спецификации" {
+       run hwkeys -load $cnt_pln:$cntname.S
+}
+
+test -title "Читаем без имени контейнера" {
+       run hwkeys -load $cnt_pln.S
+}
+
+test -title "Читаем без имени носителя"  {
+       run hwkeys -load FILECNT:$cntname.S
+}
+
+test -title "Читаем без имен контейнера и носителя" {
+       run hwkeys -load FILECNT.S
+}
+
+test -title "Читаем с именем носителя, содержащим .S" {
+       run hwkeys -load FILECNT=$cnt_pln_dot_file.S
+}
+
+end_tests
+
+proc write_cmd_file {filename args} {
+       set f [open filename w]
+       fconfigure $f -encoding binary
+       puts -nonewline $f [binary format c* $args]
+       close $f
+}
+
+test -title "Читаем, нет носителя, нет коллбэка" {
+       write_cmd_file $cnt_pln_file.cmd $cc_rc_no_contact
+       run -fail -stderr {regex {cc_rds_read_key.*==cc_rc_no_contact.*load_key failed}} \
+               hwkeys -no-cb -load $cnt_pln.S
+}
+
+test -title "Читаем, нет носителя, есть коллбэк, носитель дали"
+
+test -title "Читаем, нет носителя, есть коллбэк, запрос отменили"
+
+test -title "Читаем, есть носитель, нет контейнера"
+
+test -title "Читаем, не тот контейнер, нет коллбэка"
+
+test -title "Читаем, не тот контейнер, есть коллбэк, носитель поменяли, опять не тот, еще раз поменяли, теперь тот"
+
+test -title "Читаем, не тот контейнер, есть коллбэк, запрос отменили"
+
+test -title "Читаем, нет этого ключа (другой есть)"
+
+test -title "Читаем, ошибка чтения, нет коллбэка"
+
+test -title "Читаем, ошибка чтения, устранена"
+
+test -title "Читаем, ошибка чтения, таймаут"
+
+test -title "Читаем, ошибка чтения, отмена"
+
+test -title "Читаем, не сошлась CRC ключа"
+
+test -title "Читаем парольный, даем пароль"
+
+test -title "Читаем парольный, даем пароль со второй попытки"
+
+test -title "Читаем парольный, ошибка возврата пароля"
+
+test -title "Читаем парольный, отмена"
+
+test -title "Пишем в свежий контейнер"
+
+test -title "Проверяем подписью, что это - тот же самый ключ"
+
+test -title "Пишем в тот же контейнер второй ключ зашифрованным"
+
+test -title "Проверяем подписью, что оно"
+
+test -title "Пишем безымянный"
+
+test -title "Пишем зашифрованный, пароли совпадают со второй попытки"
+
+test -title "Пишем зашифрованный, ошибка получения пароля"
+
+test -title "Пишем зашифрованный, отмена"
+
+test -title "Ошибка записи, нет коллбэка"
+
+test -title "Ошибка записи, вернули носитель"
+
+test -title "Ошибка записи, таймаут"
+
+test -title "Ошибка записи, отмена"
+
+test -title "Нет носителя, нет коллбэка"
+
+test -title "Нет носителя, дали"
+
+test -title "Нет носителя, таймаут"
+
+test -title "Нет носителя, отмена"
+
+test -title "Не тот контейнер, нет перезаписи, нет коллбэка"
+
+test -title "Не тот контейнер, нет перезаписи, сменили носитель"
+
+test -title "Не тот контейнер, нет перезаписи, таймаут"
+
+test -title "Не тот контейнер, нет перезаписи, отмена"
+
+test -title "Не тот контейнер, есть перезапись"
+
+test -title "Ключ есть, перезапись запрещена"
+
+test -title "Ключ есть, перезапись разрешена"
+
+test -title "Затираем"
+
+test -title "Затираем, нет носителя, нет коллбэка"
+
+test -title "Затираем, нет носителя, дали носитель"
+
+test -title "Затираем, нет носителя, таймаут"
+
+test -title "Затираем, нет носителя, отмена"
+
+test -title "Затираем, не тот контейнер, нет коллбэка"
+
+test -title "Затираем, не тот контейнер, сменили носитель"
+
+test -title "Затираем, не тот контейнер, таймаут"
+
+test -title "Затираем, не тот контейнер, отмена"
+
+test -title "Затираем контейнер без имени, даем без имени"
+
+test -title "Затираем контейнер без имени, даем с именем"
diff --git a/tcl_tests/interop.try b/tcl_tests/interop.try
new file mode 100644 (file)
index 0000000..ffabc97
--- /dev/null
@@ -0,0 +1,156 @@
+#!/usr/bin/tclsh
+
+proc make_fn {alg} {
+       return [string map {":" "_"} $alg]
+}
+if {[info exists env(PKG_PATH)]} {
+       lappend auto_path $env(PKG_PATH)
+} else {       
+       lappend auto_path [file dirname [info script]]
+}
+if {![info exists env(OTHER_DIR)]} {
+   puts stderr "Environment variable OTHER_DIR not set"
+   exit 1
+} else {
+       set data_dir $env(OTHER_DIR)
+}      
+if {[file normalize $data_dir] == "[pwd]"} {
+       set suffix _bck 
+} elseif {[file normalize $data_dir] == [file normalize [pwd]/../OtherVersion]} {
+       set suffix _oth
+} else {
+       set suffix _fwd
+}      
+package require ossltest
+#cd z
+set ::test::suffix $suffix
+cd $::test::dir 
+start_tests "Интероперабельность, сравнение с $data_dir"
+
+if {[info exists env(ALG_LIST)]} {
+  set alg_list $env(ALG_LIST)
+} else {
+  set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}
+}
+if {[info exist env(ENC_LIST)]} {
+       set enc_list $env(ENC_LIST)
+} else {       
+       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:}
+}
+
+test -createsfiles cfb2.$suffix\
+"Расшифрование текста, зашифрованного на пароле в режиме CFB" {
+       set plain [getFile $data_dir/enc2.dat]
+       openssl "enc -gost89 -d -in $data_dir/cfb2.enc -out cfb2.$suffix -k 1234567890 -p"
+       set result [getFile cfb2.$suffix] 
+       expr  {[string equal $plain $result]?1:$result}
+} 0 1
+
+test -createsfiles cnt2.$suffix\
+"Расшифрование текста, зашифрованного на пароле в режиме CNT" {
+       set plain [getFile $data_dir/enc2.dat]
+       openssl "enc -gost89-cnt -d -in $data_dir/cnt2.enc -out cnt2.$suffix -k 1234567890 -p"
+       set result [getFile cnt2.$suffix] 
+       expr  {[string equal $plain $result]?1:$result}
+} 0 1
+
+test -createsfiles cbc2.$suffix\
+"Расшифрование текста, зашифрованного на пароле в режиме CBC" {
+       set plain [getFile $data_dir/enc2.dat]
+       openssl "enc -gost89-cbc -d -in $data_dir/cbc2.enc -out cbc2.$suffix -k 1234567890 -p"
+       set result [getFile cbc2.$suffix] 
+       expr  {[string equal $plain $result]?1:$result}
+} 0 1
+
+save_env2 {CRYPT_PARAMS}
+test -createsfiles cbc3.$suffix\
+"Расшифрование текста, зашифрованного в режиме CBC с параметрами РИК 1" {
+       set plain [getFile $data_dir/enc2.dat]
+       set env(CRYPT_PARAMS) "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+       openssl "enc -gost89-cbc -d -in $data_dir/cbc3.enc -out cbc3.$suffix -k 1234567890 -p"
+       set result [getFile cbc3.$suffix] 
+       expr  {[string equal $plain $result]?1:$result}
+} 0 1
+restore_env2 {CRYPT_PARAMS}
+
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username $data_dir/U_smime_$alg_fn
+       set userdir $data_dir/U_smime_${alg_fn}
+       switch -glob $alg {
+               gost2012* {set CA_dir_suffix CA-2012}
+               * {set CA_dir_suffix CA}
+       }
+
+
+test "Проверка заявки $alg" {
+       grep "verif" [openssl "req -verify -in $username/req.pem"]
+} 0 {verify OK
+}
+
+test "Проверка сертификата $alg" {
+       grep "cert.pem" [openssl "verify -CAfile $data_dir/smime$CA_dir_suffix/cacert.pem $userdir/cert.pem"]
+} 0 "$userdir/cert.pem: OK
+"
+
+test "Проверка CRL" {
+       grep verify [openssl "crl -in $data_dir/test.crl -noout -CAfile $data_dir/test_crl_cacert.pem"]
+} 0 "verify OK
+"
+
+test "Проверка документа, подписанного $alg, smime" {
+       grep Veri [openssl "smime -verify -text -in $data_dir/sign_$alg_fn.msg -out verified.$suffix -CAfile $data_dir/smime$CA_dir_suffix/cacert.pem -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+set username $data_dir/U_cms_$alg_fn
+test "Проверка документа, подписанного $alg, cms" {
+       grep Veri [openssl "cms -verify -text -in $data_dir/cms_sign_$alg_fn.msg -out cms_verified.$suffix -CAfile $data_dir/cms$CA_dir_suffix/cacert.pem -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+test -createsfiles [list extracted_cert.pem.$suffix extracted_key.pem.$suffix] "Разбираем pkcs12 c алгоритмом $alg" {
+       openssl "pkcs12 -in $data_dir/U_pkcs12_$alg_fn/pkcs12.p12 -nodes -out dump.pem.$suffix -password pass:12345"
+       set dump [getFile dump.pem.$suffix]
+       set lextr [regexp -all -inline "\n-----BEGIN .*?\n-----END \[^\n\]+-----\n" $dump]
+       
+       list [llength $lextr] [expr {[lindex $lextr 0] eq "\n[getFile $data_dir/U_pkcs12_$alg_fn/cert.pem]"}] [expr {[lindex $lextr 1] eq "\n[openssl "pkcs8 -nocrypt -topk8 -in $data_dir/U_pkcs12_$alg_fn/seckey.pem"]"}]    
+       
+} 0 {2 1 1}
+
+
+} 
+
+save_env2 {CRYPT_PARAMS}
+foreach enc_tuple $enc_list {
+       if {![regexp {^([^:]*:[^:]*):(.*)$} $enc_tuple -> alg crypt_param]} {
+               set alg $enc_tuple
+               set crypt_param {}
+       }
+       if {[string length $crypt_param]} {
+               set env(CRYPT_PARAMS) $crypt_param
+       } else {
+               if {[info exists env(CRYPT_PARAMS)]} {unset env(CRYPT_PARAMS)}
+       }
+       set alg_fn [make_fn $enc_tuple]
+       set username U_enc_$alg_fn
+
+test "Расшифрование документа на keyexchange $alg, smime" {
+       set expected [getFile $data_dir/encrypt.dat]
+       openssl "smime -decrypt -in $data_dir/enc_${alg_fn}.msg -recip $data_dir/U_enc_${alg_fn}/cert.pem -inkey $data_dir/U_enc_${alg_fn}/seckey.pem -out decrypt1.$alg_fn.$suffix"
+       set result [getFile decrypt1.$alg_fn.$suffix]
+       string eq $expected $result
+} 0 1
+
+test "Расшифрование документа на keyexchange $alg, cms" {
+       set expected [getFile $data_dir/encrypt.dat]
+       openssl "cms -decrypt -in $data_dir/cms_enc_${alg_fn}.msg -recip $data_dir/U_cms_enc_${alg_fn}/cert.pem -inkey $data_dir/U_cms_enc_${alg_fn}/seckey.pem -out cms_decrypt1.$alg_fn.$suffix"
+       set result [getFile cms_decrypt1.$alg_fn.$suffix]
+       string eq $expected $result
+} 0 1
+
+
+}
+restore_env2 {CRYPT_PARAMS}
+end_tests
diff --git a/tcl_tests/kbstrike.exe b/tcl_tests/kbstrike.exe
new file mode 100755 (executable)
index 0000000..542919a
Binary files /dev/null and b/tcl_tests/kbstrike.exe differ
diff --git a/tcl_tests/key.pem b/tcl_tests/key.pem
new file mode 100644 (file)
index 0000000..bb4c7bc
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGMMEAGCSqGSIb3DQEFDTAzMBsGCSqGSIb3DQEFDDAOBAi26UdKOFk+lgICCAAw
+FAYIKoZIhvcNAwcECGp4Z7XaD/vABEgfBlfcpKTWrDqMjzd2qra/uR5u+ogSKp3b
+CBLudt8opsMfrCrIUJk6NpTP1BVPa4nYqqKePWIY7p6S3pSxQWBkhsWmM7G3K/w=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tcl_tests/mac-grasshopper.dat b/tcl_tests/mac-grasshopper.dat
new file mode 100644 (file)
index 0000000..0fc0f32
Binary files /dev/null and b/tcl_tests/mac-grasshopper.dat differ
diff --git a/tcl_tests/mac-magma.dat b/tcl_tests/mac-magma.dat
new file mode 100644 (file)
index 0000000..12f236b
--- /dev/null
@@ -0,0 +1,2 @@
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
diff --git a/tcl_tests/mac.try b/tcl_tests/mac.try
new file mode 100644 (file)
index 0000000..de2cb6b
--- /dev/null
@@ -0,0 +1,121 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду dgst с MAC"
+
+test -createsfiles {dgst.dat dgst0.dat dgst2.dat dgst8.dat dgst63.dat mac-grasshopper.dat mac-magma.dat} "Формирование тестовых данных" {
+       makeFile dgst.dat [string repeat "Test data to digest.\n" 100] binary
+       makeFile dgst0.dat "" binary
+       makeFile dgst2.dat [string repeat "1\n" 1] binary
+       makeFile dgst8.dat [string repeat "1\n" 4] binary
+       makeFile dgst63.dat "012345678901234567890123456789012345678901234567890123456789012" binary
+       file copy -force ../mac-grasshopper.dat ../mac-magma.dat .
+} 0 ""
+
+test "Вычисление HMAC(md_gost12_512)" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 -mac hmac -macopt key:123456901234567890123456789012 dgst63.dat"]
+} 0 "HMAC-md_gost12_512(dgst63.dat)= 3767bcbe31de0965a6cd2613d99cc8cda922e7b288478389ed9bd433abfc08ff61d9bd0257b2d14dd0648d04ebf056180b3c8739a7cd7f8a78dac856359fe26f\n"
+
+test "Вычисление двух HMAC(md_gost12_512)" {
+       grep "md_gost12_512\\(" [openssl "dgst -md_gost12_512 -mac hmac -macopt key:123456901234567890123456789012 dgst63.dat dgst63.dat"]
+} 0 "HMAC-md_gost12_512(dgst63.dat)= 3767bcbe31de0965a6cd2613d99cc8cda922e7b288478389ed9bd433abfc08ff61d9bd0257b2d14dd0648d04ebf056180b3c8739a7cd7f8a78dac856359fe26f\nHMAC-md_gost12_512(dgst63.dat)= 3767bcbe31de0965a6cd2613d99cc8cda922e7b288478389ed9bd433abfc08ff61d9bd0257b2d14dd0648d04ebf056180b3c8739a7cd7f8a78dac856359fe26f\n"
+
+test "Вычисление HMAC(md_gost94)" {
+       grep "md_gost94\\(" [openssl "dgst -md_gost94 -mac hmac -macopt key:123456901234567890123456789012 dgst.dat"]
+} 0 "HMAC-md_gost94(dgst.dat)= 25434aa4b59b9749d3716ac188762b6c92b47d552aeb556f74b9c357b2b7c8c6\n"
+
+test "Вычисление двух HMAC(md_gost94)" {
+       grep "md_gost94\\(" [openssl "dgst -md_gost94 -mac hmac -macopt key:123456901234567890123456789012 dgst.dat dgst.dat"]
+} 0 "HMAC-md_gost94(dgst.dat)= 25434aa4b59b9749d3716ac188762b6c92b47d552aeb556f74b9c357b2b7c8c6\nHMAC-md_gost94(dgst.dat)= 25434aa4b59b9749d3716ac188762b6c92b47d552aeb556f74b9c357b2b7c8c6\n"
+
+test "Попытка вычислить MAC с ключом неправильной длины" {
+       grep gost-mac [openssl "dgst -mac gost-mac  -macopt key:123456789012345678901234567890 dgst.dat"]
+} 1 "invalid mac key length"
+
+test "Попытка вычислить MAC с hex ключом неправильной длины" {
+       grep gost-mac [openssl "dgst -mac gost-mac  -macopt hexkey:414243444546474849404142434445464748494041424344454647484940 dgst.dat"]
+} 1 "invalid mac key length"
+
+test "Вычисление MAC gost89" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst.dat"]
+} 0 "GOST-MAC-gost-mac(dgst.dat)= 37f646d2\n"
+
+test "Вычисление двух MAC gost89" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst.dat dgst.dat"]
+} 0 "GOST-MAC-gost-mac(dgst.dat)= 37f646d2\nGOST-MAC-gost-mac(dgst.dat)= 37f646d2\n"
+
+test "Вычислиение MAC gost89 с шестнацатиричным ключом" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt hexkey:3132333435363738393031323334353637383930313233343536373839303132 dgst.dat"]
+} 0 "GOST-MAC-gost-mac(dgst.dat)= 37f646d2\n"
+
+test "Вычисление MAC gost89 от файла нулевой длины" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst0.dat"]
+} 0 "GOST-MAC-gost-mac(dgst0.dat)= 00000000\n"
+
+test "Вычисление MAC gost89 от файла длины 2" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst2.dat"]
+} 0 "GOST-MAC-gost-mac(dgst2.dat)= 87ea321f\n"
+
+test "Вычисление MAC gost89 от файла длины 8" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= ad9aeae0\n"
+
+test "Вычисление MAC gost8912" {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= be70ba5e\n"
+
+test "Вычисление MAC gost89 со сменой параметров на параметры от gost8912 (symbolic)" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 -macopt paramset:id-tc26-gost-28147-param-Z dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= be70ba5e\n"
+
+test "Вычисление MAC gost8912 со сменой параметров на параметры от gost89 (OID)" {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -macopt paramset:1.2.643.2.2.31.1 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= ad9aeae0\n"
+
+test "Вычисление MAC gost89 со сменой параметров на параметры 1.2.643.2.2.31.2" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 -macopt paramset:1.2.643.2.2.31.2 dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= c7fdc644\n"
+
+test "Вычисление MAC gost8912 со сменой параметров на параметры id-Gost28147-89-CryptoPro-B-ParamSet" {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -macopt paramset:id-Gost28147-89-CryptoPro-B-ParamSet dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= c7fdc644\n"
+
+test "Вычисление MAC gost89 с изменение длины имитовставки (8)" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 -sigopt size:8 dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= ad9aeae05a7f6f71\n"
+
+test "Вычисление MAC gost8912 с изменение длины имитовставки (6)" {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -sigopt size:6 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= be70ba5ed6b0\n"
+
+test "Вычисление MAC gost89 с изменение длины имитовставки (2)" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 -sigopt size:3 dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= ad9aea\n"
+
+test "Вычисление MAC gost89 с изменение длины имитовставки через macopt" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 -macopt size:3 dgst8.dat"]
+} 0 "GOST-MAC-gost-mac(dgst8.dat)= ad9aea\n"
+
+test "Вычисление MAC gost8912 с изменение длины имитовставки через macopt" {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -macopt size:6 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= be70ba5ed6b0\n"
+
+test "Вычисление MAC gost8912 с изменение длины имитовставки:sigopt переписывает macopt " {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -macopt size:2 -sigopt size:6 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= be70ba5ed6b0\n"
+
+test "Вычисление MAC gost8912 с изменение длины имитовставки:sigopt переписывает macopt " {
+       grep gost-mac [openssl "dgst -mac gost-mac-12 -macopt key:12345678901234567890123456789012 -macopt size:2 -sigopt size:6 dgst8.dat"]
+} 0 "GOST-MAC-12-gost-mac-12(dgst8.dat)= be70ba5ed6b0\n"
+
+test "Вычисление MAC magma-mac (пример из ГОСТ 2015 34.13)" {
+       grep magma-mac [openssl "dgst -mac magma-mac -macopt hexkey:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff mac-magma.dat"]
+} 0 "MAGMA-MAC-magma-mac(mac-magma.dat)= 154e72102030c5bb\n"
+
+test "Вычисление MAC grasshopper-mac (пример из ГОСТ 2015 34.13)" {
+       grep grasshopper-mac [openssl "dgst -mac grasshopper-mac -macopt hexkey:8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef mac-grasshopper.dat"]
+} 0 "GRASSHOPPER-MAC-grasshopper-mac(mac-grasshopper.dat)= 336f4d296059fbe34ddeb35b37749c67\n"
+
+end_tests
diff --git a/tcl_tests/macpkm1.enc b/tcl_tests/macpkm1.enc
new file mode 100644 (file)
index 0000000..ccbd14e
Binary files /dev/null and b/tcl_tests/macpkm1.enc differ
diff --git a/tcl_tests/magma1.enc b/tcl_tests/magma1.enc
new file mode 100644 (file)
index 0000000..c14cb49
--- /dev/null
@@ -0,0 +1 @@
+N\98\11\f\97·¹<>%\r\93Öè]i\13m\86\88\a²ÛïV\8e\80«R¡-
\ No newline at end of file
diff --git a/tcl_tests/magma_acpkm_plain.enc b/tcl_tests/magma_acpkm_plain.enc
new file mode 100644 (file)
index 0000000..d67f00c
Binary files /dev/null and b/tcl_tests/magma_acpkm_plain.enc differ
diff --git a/tcl_tests/magma_enc b/tcl_tests/magma_enc
new file mode 100644 (file)
index 0000000..c14cb49
--- /dev/null
@@ -0,0 +1 @@
+N\98\11\f\97·¹<>%\r\93Öè]i\13m\86\88\a²ÛïV\8e\80«R¡-
\ No newline at end of file
diff --git a/tcl_tests/magma_plain b/tcl_tests/magma_plain
new file mode 100644 (file)
index 0000000..12f236b
--- /dev/null
@@ -0,0 +1,2 @@
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
diff --git a/tcl_tests/magma_plain.enc b/tcl_tests/magma_plain.enc
new file mode 100644 (file)
index 0000000..12f236b
--- /dev/null
@@ -0,0 +1,2 @@
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
diff --git a/tcl_tests/make_other.sh b/tcl_tests/make_other.sh
new file mode 100755 (executable)
index 0000000..ed9d9e8
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+# -*- coding: cp1251 -*-
+
+# Создает подкаталог OtherVersion, копирует в него данные для тестирования
+# совместимости с другими версиями.
+# Данные берутся из результатов прогона тестов для открытого энжина 
+# (поскольку именно он гарантированно умеет все нужные алгоритмы, 
+# включая устаревшие).
+
+TESTDIR=`hostname`-gost
+SAVEDIR=OtherVersion
+if ! [ -d ${TESTDIR} ]; then
+       echo $TESTDIR does not exist.
+       exit 1
+fi 
+[ -d ${SAVEDIR} ] && rm -fr ${SAVEDIR}
+mkdir ${SAVEDIR}
+cd ${TESTDIR}
+cp -rp enc.enc enc.dat ../$SAVEDIR
+cp -rp smimeCA test.crl test_crl_cacert.pem ../$SAVEDIR
+cp -rp U_smime_* sign_*.msg ../$SAVEDIR
+cp -rp cmsCA U_cms_* cms_sign_*.msg ../$SAVEDIR
+cp -rp U_pkcs12_* ../$SAVEDIR
+cp -rp encrypt.dat U_enc_* enc_*.msg ../$SAVEDIR
+cp -rp U_cms_enc_* cms_enc_*.msg ../$SAVEDIR
diff --git a/tcl_tests/mkn2o.tcl b/tcl_tests/mkn2o.tcl
new file mode 100644 (file)
index 0000000..256b2a0
--- /dev/null
@@ -0,0 +1,28 @@
+proc oid {oid name types} {
+       global new_name2oid
+       set new_name2oid($name) $oid
+}
+
+source [lindex $argv 0]
+source name2oid.tcl
+
+set differ 0
+foreach name [array names name2oid] {
+       if {![info exists new_name2oid($name)] || $new_name2oid($name) != $name2oid($name)} {set differ 1}
+}
+if {!$differ} {
+       foreach name [array names new_name2oid] {
+               if {![info exists name2oid($name)]} {set differ 1}
+       }
+}
+
+if {$differ} {
+       set n2of [open name2oid.tcl w]
+       puts $n2of "array set name2oid {"
+       foreach name [lsort [array names new_name2oid]] {
+               puts $n2of "$name $new_name2oid($name)"
+       }
+       puts $n2of "}"
+       close $n2of
+}
+
diff --git a/tcl_tests/mkoidf.tcl b/tcl_tests/mkoidf.tcl
new file mode 100644 (file)
index 0000000..c08e015
--- /dev/null
@@ -0,0 +1,5 @@
+proc oid {oid name types} {
+       puts "$oid $name GOST $name $oid"
+}
+
+source [lindex $argv 0]
diff --git a/tcl_tests/name2oid.tcl b/tcl_tests/name2oid.tcl
new file mode 100644 (file)
index 0000000..fc2e639
--- /dev/null
@@ -0,0 +1,44 @@
+array set name2oid {
+crypt89_cc 1.2.643.2.2.21
+mac89 1.2.643.2.2.22
+pk_sign94_cc 1.2.643.2.9.1.5.3
+pk_sign94_cp 1.2.643.2.2.20
+pk_sign01_cc 1.2.643.2.9.1.5.4
+pk_sign01_cp 1.2.643.2.2.19
+pk_sign12_256 1.2.643.7.1.1.1.1
+pk_sign12_512 1.2.643.7.1.1.1.2
+hash_94 1.2.643.2.2.9
+hash_12_256 1.2.643.7.1.1.2.2
+hash_12_512 1.2.643.7.1.1.2.3
+hash_with_sign94_cc 1.2.643.2.9.1.3.3
+hash_with_sign94_cp 1.2.643.2.2.4
+hash_with_sign01_cc 1.2.643.2.9.1.3.4
+hash_with_sign01_cp 1.2.643.2.2.3
+hash_with_sign12_256 1.2.643.7.1.1.3.2
+hash_with_sign12_512 1.2.643.7.1.1.3.3
+param_encr_cc 1.2.643.2.9.1.6.1
+param_encr_cpa 1.2.643.2.2.31.1
+param_encr_cpb 1.2.643.2.2.31.2
+param_encr_cpc 1.2.643.2.2.31.3
+param_encr_cpd 1.2.643.2.2.31.4
+param_encr_cptest 1.2.643.2.2.31.0
+param_encr_tc 1.2.643.7.1.2.5.1.1
+param_hash_94 1.2.643.2.2.30.1
+param_pubkey94_cpa 1.2.643.2.2.32.2
+param_pubkey94_cpb 1.2.643.2.2.32.3
+param_pubkey94_cpc 1.2.643.2.2.32.4
+param_pubkey94_cpd 1.2.643.2.2.32.5
+param_pubkey94_cpxcha 1.2.643.2.2.33.1
+param_pubkey94_cpxchb 1.2.643.2.2.33.2
+param_pubkey94_cpxchc 1.2.643.2.2.33.3
+param_pubkey01_cc 1.2.643.2.9.1.8.1
+param_pubkey01_cpa 1.2.643.2.2.35.1
+param_pubkey01_cpb 1.2.643.2.2.35.2
+param_pubkey01_cpc 1.2.643.2.2.35.3
+param_pubkey01_cptest 1.2.643.2.2.35.0
+param_pubkey01_cpxcha 1.2.643.2.2.36.0
+param_pubkey01_cpxchb 1.2.643.2.2.36.1
+param_pubkey12_512_0 1.2.643.7.1.2.1.2.0
+param_pubkey12_512_A 1.2.643.7.1.2.1.2.1
+param_pubkey12_512_B 1.2.643.7.1.2.1.2.2
+}
diff --git a/tcl_tests/name2oid.tst b/tcl_tests/name2oid.tst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tcl_tests/nopath.try b/tcl_tests/nopath.try
new file mode 100644 (file)
index 0000000..c3664ae
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Подгрузка engine без явно указанного dynamic_path"
+
+set config [getConfig]
+regexp {\ndynamic_path\s*=\s*(\S[^\n]+)} $config => path
+if [file exist [file join [file dirname $::OPENSSL_CONF] cryptocom.lic]] {
+file copy -force [file join [file dirname $::OPENSSL_CONF] cryptocom.lic] cryptocom.lic
+}
+if {[info exists path]} {
+       set env(OPENSSL_ENGINES) [subst -nocommands -nobackslashes [regsub {\$ENV::(\w+)} [file dirname $path] {$env(\1)}]]
+       puts $env(OPENSSL_ENGINES)
+       makeFile nodp.conf [regsub  {\ndynamic_path\s*=\s*([^\n]+)} $config {}]
+       set env(OPENSSL_CONF) "[pwd]/nodp.conf"
+}
+test -platformex {[info exists path]} -createsfiles dgst.dat  "Вычисление дайджеста md_gost94" {
+       makeFile dgst.dat [string repeat "Test data to digest.\n" 100] binary
+               grep "md_gost94\\(" [openssl "dgst -md_gost94 dgst.dat"]
+} 0 "md_gost94\(dgst.dat)= 42e462ce1c2b4bf72a4815b7b4877c601f05e5781a71eaa36f63f836c021865c\n"
+
+set plain "Test data to encrypt"
+test -platformex {[info exists path]} -createsfiles {enc.enc enc.dat} "Encrypting file in CFB mode" {
+       makeFile enc.dat $plain binary
+       openssl "enc -gost89 -out enc.enc -in enc.dat -k 1234567890 -p"
+       file isfile enc.enc
+} 0 1
+
+test -platformex {[info exists path]} -createsfiles {cnt.enc} "Encrypting file in CNT mode" {
+       makeFile enc.dat $plain binary
+       openssl "enc -gost89-cnt -out cnt.enc -in enc.dat -k 1234567890 -p"
+       file isfile cnt.enc
+} 0 1
+
+test -platformex {[info exists path]} -skip {![file exists enc.enc]} "Ciphered text in CFB mode  differs from clear text" {
+       set ciphered [getFile enc.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test -platformex {[info exists path]} -skip {![file exists cnt.enc]} "Ciphered text in CNT mode  differs from clear text" {
+       set ciphered [getFile cnt.enc binary]
+       string first $ciphered $plain
+} 0 -1
+
+test -platformex {[info exists path]} -skip {![file exists enc.enc]} -createsfiles enc.dec "Decrypting file, encrypted in CFB mode" {
+       openssl "enc -gost89 -d -in enc.enc -out enc.dec -k 1234567890 -p"
+       getFile enc.dec 
+} 0 $plain
+
+test -platformex {[info exists path]} -skip {![file exists cnt.enc]} -createsfiles cnt.dec "Decrypting file, encrypted in CNT mode" {
+       openssl "enc -gost89-cnt -d -in cnt.enc -out cnt.dec -k 1234567890 -p"
+       getFile cnt.dec 
+} 0 $plain
+
+test -platformex {[info exists path]} "Вычисление MAC gost89" {
+       grep gost-mac [openssl "dgst -mac gost-mac -macopt key:12345678901234567890123456789012 dgst.dat"]
+} 0 "GOST-MAC-gost-mac(dgst.dat)= 37f646d2\n"
+
+test -platformex {[info exists path]} -createsfiles nodp2001.key "Создание секретного ключа gost2001" {
+       makeSecretKey nodp2001 gost2001:A
+       file exists nodp2001/seckey.pem
+} 0 1  
+
+
+file delete cryptocom.lic
+end_tests
diff --git a/tcl_tests/ocsp.try b/tcl_tests/ocsp.try
new file mode 100644 (file)
index 0000000..30c1218
--- /dev/null
@@ -0,0 +1,153 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir 
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на OCSP-запросы и ответы"
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2012_256:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2012_256:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_smime_$alg_fn
+
+test "Creating CA" { 
+       makeCA ${testname}CA-$alg_fn $alg
+} 0 1
+
+after 1000
+
+set server_args "-index $::test::ca/index.txt -rsigner $::test::ca/cacert.pem -rkey $::test::ca/private/cakey.pem -CA $::test::ca/cacert.pem -noverify"
+set client_args "-issuer $::test::ca/cacert.pem -CAfile $::test::ca/cacert.pem"
+
+test "Создаем юзера" {
+       makeRegisteredUser U_ocsp_$alg_fn $alg
+       makeRegisteredUser U_ocsp2_$alg_fn $alg
+       file exists U_ocsp_$alg_fn/cert.pem
+} 0 1
+
+after 1000
+
+test -createsfiles {request1.der} "Создаеем неподписанный запрос SHA1 хэш  по сертификату" {
+       openssl "ocsp $client_args -cert U_ocsp_$alg_fn/cert.pem -reqout request1.der"
+       file exists request1.der
+} 0 1
+
+test -skip {![file exists request1.der]} "Анализируем OID-ы в запросе" {
+       extract_oids request1.der DER
+} 0 " OBJECT            :sha1
+"
+
+test -skip {![file exists request1.der]} -createsfiles {response1.der} "Формируем ГОСТ-подписанный ответ" {
+       openssl "ocsp $server_args -reqin request1.der -respout response1.der"
+} 0 ""
+
+test -skip {![file exists request1.der]} "Анализируем OID-ы в ответе" {
+       extract_oids response1.der DER 30
+} 0  " OBJECT            :sha1\n[mkObjList [hash_with_sign_long_name $alg] [hash_with_sign_long_name $alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [hash_with_sign_long_name $alg]]"
+
+
+test -skip {![file exists response1.der]} "Проверяем ГОСТ-подписанный ответ" {
+       openssl "ocsp $client_args -respin response1.der"       
+
+} 0 "STDERR CONTENTS:\nResponse verify OK"
+
+test -skip {![file exists response1.der]} "Проверяем статус сертификата" {
+       grep "Cert Status" [openssl "ocsp -respin response1.der -text -CAfile $::test::ca/cacert.pem"]
+} 0 "    Cert Status: good\n"
+
+test -createsfiles request2.der "Формируем ГОСТ-подписанный запрос с хэшом SHA1 по сертификату" {
+       openssl "ocsp $client_args -cert U_ocsp_$alg_fn/cert.pem -signer U_ocsp_$alg_fn/cert.pem -signkey U_ocsp_$alg_fn/seckey.pem -reqout request2.der" 
+
+} 0 ""
+
+test -skip {![file exists request2.der]} "Анализируем OID-ы в запросе" {
+       extract_oids request2.der DER
+} 0  " OBJECT            :sha1\n[mkObjList [hash_with_sign_long_name $alg] [hash_with_sign_long_name $alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [hash_with_sign_long_name $alg]]"
+
+
+test -createsfiles response2.der -skip {![file exists request2.der]} "Формируем ответ на подписанный запрос" {
+       openssl "ocsp $server_args -reqin request2.der -respout response2.der"
+       file exists response2.der
+} 0 1
+
+test -skip {![file exists response2.der]} "Проверяем ответ на запрос 2" {        
+       grep "Response .erif" [openssl "ocsp $client_args -respin response2.der"]
+} 0 "Response verify OK\n"
+
+test -createsfiles request3.der "Формируем запрос с ГОСТ-овским хэшом по сертификату" {
+       openssl "ocsp $client_args -[hash_short_name [alg_hash $alg]] -cert U_ocsp_$alg_fn/cert.pem -reqout request3.der" 
+       file exists request3.der 
+} 0 1
+
+test -skip {![file exists request3.der]} "Анализируем OID-ы в запросе" {
+       extract_oids request3.der DER
+} 0 [mkObjList [hash_long_name $alg]]
+
+test -skip {![file exists request3.der]} -createsfiles response3.der "Формируем ответ на запрос с ГОСТ-овским хэшом" {
+       openssl "ocsp $server_args  -reqin request3.der -respout response3.der"
+       file exists response3.der       
+} 0 1
+
+test -skip {![file exists response3.der] } "Проверяем ответ на запрос 3" {
+       grep "Response .erif" [openssl "ocsp -[hash_short_name [alg_hash $alg]] $client_args -respin response3.der"]
+} 0 "Response verify OK\n"
+
+
+test -skip {![file exists response3.der]} "Проверяем статус сертификата" {
+       grep "Cert Status" [openssl "ocsp -respin response3.der -text -CAfile $::test::ca/cacert.pem"]
+} 0 "    Cert Status: good\n"
+
+test -createsfiles request4.der "Формируем запрос с ГОСТ-овским хэшом по serial" {
+       openssl "ocsp $client_args -[hash_short_name [alg_hash $alg]] -serial 0x11E -reqout request4.der" 
+} 0 ""
+
+test -skip {![file exists request4.der]} "Проверяем OID-ы в запросе 4" {
+       extract_oids request4.der DER
+} 0 [mkObjList [hash_long_name $alg]]
+
+
+test -skip {![file exists request4.der]} -createsfiles response4.der "Формируем ответ на запрос с ГОСТ-овским хэшом" {
+       openssl "ocsp $server_args -reqin request4.der -respout response4.der"
+       file exists response4.der
+} 0 1
+
+test -skip {![file exists response4.der] } "Проверяем ответ на запрос 4" {
+       grep "Response .erif" [openssl "ocsp $client_args -respin response4.der"]
+} 0 "Response verify OK\n"
+
+test -createsfiles request5.der "Формируем запрос с двумя сертификатами и разными хэшами" {
+       openssl "ocsp $client_args -[hash_short_name [alg_hash $alg]] -cert U_ocsp_$alg_fn/cert.pem -sha1 -cert U_ocsp2_$alg_fn/cert.pem -reqout request5.der" 
+} 0 ""
+
+test -skip {![file exists request5.der]} "Проверяем OID-ы в запросе 5" {
+       extract_oids request5.der DER
+} 0 "[mkObjList [hash_long_name $alg]] OBJECT            :sha1\n"
+
+
+test -skip {![file exists request5.der]} -createsfiles response5.der "Формируем ответ на запрос с двумя хэшами" {
+       openssl "ocsp $server_args -reqin request5.der -respout response5.der"
+       file exists response5.der
+} 0 1
+
+test -skip {![file exists response5.der] } "Проверяем ответ на запрос 5" {
+       grep "Response .erif" [openssl "ocsp -[hash_short_name [alg_hash $alg]] $client_args -respin response5.der"]
+} 0 "Response verify OK\n"
+
+test -skip {![file exists response5.der]} "Проверяем статус сертификатoв" {
+       grep "Cert Status" [openssl "ocsp -respin response5.der -text -CAfile $::test::ca/cacert.pem"]
+} 0 "    Cert Status: good\n    Cert Status: good\n"
+
+}
+
+end_tests
+
diff --git a/tcl_tests/oidfile b/tcl_tests/oidfile
new file mode 100644 (file)
index 0000000..723e542
--- /dev/null
@@ -0,0 +1,43 @@
+1.2.643.2.2.9 hash_94 GOST hash_94 1.2.643.2.2.9
+1.2.643.7.1.1.2.2 hash_12_256 GOST hash_12_256 1.2.643.7.1.1.2.2
+1.2.643.7.1.1.2.3 hash_12_512 GOST hash_12_512 1.2.643.7.1.1.2.3
+1.2.643.2.2.30.1 param_hash_94 GOST param_hash_94 1.2.643.2.2.30.1
+1.2.643.2.2.21 crypt89_cc GOST crypt89_cc 1.2.643.2.2.21
+1.2.643.2.2.22 mac89 GOST mac89 1.2.643.2.2.22
+1.2.643.2.9.1.6.1 param_encr_cc GOST param_encr_cc 1.2.643.2.9.1.6.1
+1.2.643.2.2.31.0 param_encr_cptest GOST param_encr_cptest 1.2.643.2.2.31.0
+1.2.643.2.2.31.1 param_encr_cpa GOST param_encr_cpa 1.2.643.2.2.31.1
+1.2.643.2.2.31.2 param_encr_cpb GOST param_encr_cpb 1.2.643.2.2.31.2
+1.2.643.2.2.31.3 param_encr_cpc GOST param_encr_cpc 1.2.643.2.2.31.3
+1.2.643.2.2.31.4 param_encr_cpd GOST param_encr_cpd 1.2.643.2.2.31.4
+1.2.643.7.1.2.5.1.1 param_encr_tc GOST param_encr_tc 1.2.643.7.1.2.5.1.1
+1.2.643.2.2.4 hash_with_sign94_cp GOST hash_with_sign94_cp 1.2.643.2.2.4
+1.2.643.2.9.1.3.3 hash_with_sign94_cc GOST hash_with_sign94_cc 1.2.643.2.9.1.3.3
+1.2.643.2.2.3 hash_with_sign01_cp GOST hash_with_sign01_cp 1.2.643.2.2.3
+1.2.643.2.9.1.3.4 hash_with_sign01_cc GOST hash_with_sign01_cc 1.2.643.2.9.1.3.4
+1.2.643.7.1.1.3.2 hash_with_sign12_256 GOST hash_with_sign12_256 1.2.643.7.1.1.3.2
+1.2.643.7.1.1.3.3 hash_with_sign12_512 GOST hash_with_sign12_512 1.2.643.7.1.1.3.3
+1.2.643.2.2.20 pk_sign94_cp GOST pk_sign94_cp 1.2.643.2.2.20
+1.2.643.2.9.1.5.3 pk_sign94_cc GOST pk_sign94_cc 1.2.643.2.9.1.5.3
+1.2.643.2.2.19 pk_sign01_cp GOST pk_sign01_cp 1.2.643.2.2.19
+1.2.643.2.9.1.5.4 pk_sign01_cc GOST pk_sign01_cc 1.2.643.2.9.1.5.4
+1.2.643.7.1.1.1.1 pk_sign12_256 GOST pk_sign12_256 1.2.643.7.1.1.1.1
+1.2.643.7.1.1.1.2 pk_sign12_512 GOST pk_sign12_512 1.2.643.7.1.1.1.2
+1.2.643.2.2.32.2 param_pubkey94_cpa GOST param_pubkey94_cpa 1.2.643.2.2.32.2
+1.2.643.2.2.32.3 param_pubkey94_cpb GOST param_pubkey94_cpb 1.2.643.2.2.32.3
+1.2.643.2.2.32.4 param_pubkey94_cpc GOST param_pubkey94_cpc 1.2.643.2.2.32.4
+1.2.643.2.2.32.5 param_pubkey94_cpd GOST param_pubkey94_cpd 1.2.643.2.2.32.5
+1.2.643.2.2.33.1 param_pubkey94_cpxcha GOST param_pubkey94_cpxcha 1.2.643.2.2.33.1
+1.2.643.2.2.33.2 param_pubkey94_cpxchb GOST param_pubkey94_cpxchb 1.2.643.2.2.33.2
+1.2.643.2.2.33.3 param_pubkey94_cpxchc GOST param_pubkey94_cpxchc 1.2.643.2.2.33.3
+1.2.643.2.2.35.0 param_pubkey01_cptest GOST param_pubkey01_cptest 1.2.643.2.2.35.0
+1.2.643.2.2.35.1 param_pubkey01_cpa GOST param_pubkey01_cpa 1.2.643.2.2.35.1
+1.2.643.2.2.35.2 param_pubkey01_cpb GOST param_pubkey01_cpb 1.2.643.2.2.35.2
+1.2.643.2.2.35.3 param_pubkey01_cpc GOST param_pubkey01_cpc 1.2.643.2.2.35.3
+1.2.643.2.2.36.0 param_pubkey01_cpxcha GOST param_pubkey01_cpxcha 1.2.643.2.2.36.0
+1.2.643.2.2.36.1 param_pubkey01_cpxchb GOST param_pubkey01_cpxchb 1.2.643.2.2.36.1
+1.2.643.2.9.1.8.1 param_pubkey01_cc GOST param_pubkey01_cc 1.2.643.2.9.1.8.1
+1.2.643.7.1.2.1.2.0 param_pubkey12_512_0 GOST param_pubkey12_512_0 1.2.643.7.1.2.1.2.0
+1.2.643.7.1.2.1.2.1 param_pubkey12_512_A GOST param_pubkey12_512_A 1.2.643.7.1.2.1.2.1
+1.2.643.7.1.2.1.2.2 param_pubkey12_512_B GOST param_pubkey12_512_B 1.2.643.7.1.2.1.2.2
+
diff --git a/tcl_tests/opnssl.sh b/tcl_tests/opnssl.sh
new file mode 100755 (executable)
index 0000000..e51726d
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+export HSTNME=`hostname`
+
+if test $HSTNME = tls-ref-cp10; then ossl=/usr/bin/openssl; fi
+if test $HSTNME = tls-ref-cp20; then ossl=/opt/cryptopack2/bin/openssl; fi
+if test $HSTNME = tls-ref-cp21; then ossl=/opt/cryptopack2/bin/openssl; fi
+
+$ossl $*
+
+exit $?
diff --git a/tcl_tests/ossltest.tcl b/tcl_tests/ossltest.tcl
new file mode 100644 (file)
index 0000000..c02d566
--- /dev/null
@@ -0,0 +1,1052 @@
+#
+# Расширение пакета test для OpenSSL
+#
+package require http
+# Путь поиска пакета test
+if {[info exists env(TOOLDIR)]} {
+       lappend auto_path $env(TOOLDIR)
+} {
+       lappend auto_path "[file dirname [info script]]/../../maketool"
+}
+
+
+# outputs specified environment variables into log
+
+proc log_vars {args} {
+       foreach var $args {
+               if [info exists ::env($var)] {
+                       log $var=$::env($var)
+               } else {
+                       log "$var is not set"
+               }       
+       }
+}      
+# Проверка наличия необходимых переменных окружения
+foreach var {OPENSSL_APP} {
+if {![info exists env($var)]} {
+       puts stderr "Environment variable $var not defined"
+       exit 100
+} else {
+       set $var [file normalize $env($var)]
+}
+}
+
+if {[info exists env(OPENSSL_CONF)]} {
+       set OPENSSL_CONF $env(OPENSSL_CONF)
+} else {
+       if {[regexp {OPENSSLDIR: "([^\"]+)"} [exec $OPENSSL_APP version -d] => openssl_dir]} {
+               set OPENSSL_CONF $openssl_dir/openssl.cnf
+       } else {        
+               puts stderr "Cannot find out default openssl config"
+               exit 100
+       }
+}      
+
+if {![file exists $OPENSSL_CONF]} {
+       puts "Configuration file $OPENSSL_CONF doesn't exist"
+       exit 100
+}      
+
+if {$::tcl_platform(platform) != "windows"} {
+  proc kill {signal pid} {
+  exec kill -$signal $pid
+  }
+} else {
+  proc kill {signal pid} {
+  exec taskkill /pid $pid /f
+  }
+}
+       
+package require test
+set test::suffix ""
+package require base64
+
+#
+# set  up test::dir variable
+#
+
+if {[info exists env(TESTDIR)]} {
+       set ::test::dir [file normalize $env(TESTDIR)]
+} else {
+       set ::test::dir [file join [pwd] z]
+}      
+
+#
+# Фильтрует вывод полученный в виде длинной строки, разбивая на строки
+# по \n. Возвращает строки, удовлетворяющие регулярному выражениу
+# pattern
+#
+
+proc grep {pattern data} {
+       set out ""
+       foreach line [split $data "\n"] {
+               if {[regexp $pattern $line]} {
+                       append out $line "\n"
+               }
+       }       
+       return $out
+}      
+proc check_builtin_engine {} {
+       global OPENSSL_APP
+       set found [regexp Cryptocom [exec $OPENSSL_APP engine 2> /dev/null]]
+       if {$found} {
+               puts "Using statically compiled engine"
+       } else {
+               puts "Using dynamically loaded engine"
+       }
+       return $found
+}      
+       
+
+# Вызывает команду openssl.
+# Посылает в лог вывод на stdout и на stderr, возвращает его же.
+proc openssl {cmdline} {
+       global ENGINE_PATH OPENSSL_APP
+       log_vars OPENSSL_CONF CRYPT_PARAMS RNG RNG_PARAMS CCENGINE_LICENSE
+       if {[info exists ::test::engine]} {
+               set cmdline [concat [lrange $cmdline 0 0] [list -engine $::test::engine] [lrange $cmdline 1 end]]
+       }       
+       log "OpenSSL cmdline: $OPENSSL_APP $cmdline"
+       set f [open "|$OPENSSL_APP $cmdline" r]
+       set output [read $f]
+       if {[catch {close $f} msg]} {
+               append output "STDERR CONTENTS:\n$msg"
+               log $output
+               if {[lindex $::errorCode 0]!="NONE"} {
+                       return -code error -errorcode $::errorCode $output
+               }
+       }       
+       return $output
+}      
+
+
+proc getConfig {args} {
+       global OPENSSL_CONF
+       if {![info exists OPENSSL_CONF]} {
+         if {![regexp "OPENSSLDIR: \"\[^\"\]+\"" [openssl version -d] => openssl_dir]} {
+               puts stderr "Cannot find out openssl directory"
+               exit 1
+         }
+        set OPENSSL_CONF  "$openssl_dir/openssl.cnf"
+       }
+       set f [open $OPENSSL_CONF r]
+       set out ""
+       set mode copy
+       while {[gets $f line]>=0} {
+               if {[regexp     "\\s*\\\[\\s*(\\S+)\\s*\\\]" $line => section]} {
+                       if {[lsearch -exact $args $section]!=-1} {
+                               set mode skip
+                       } else {
+                               set mode copy
+                       }
+               }
+               if {$mode eq "copy"} {
+                       append out $line \n
+               }       
+        }      
+        return $out
+}       
+#
+# Создает тестовый CA
+# Допустимые параметры: 
+# CAname - директория, в которой создается CA (testCA по умолчанию)
+# алгоритм с параметрами в формате команды req
+#
+
+proc makeCA {{CAname {}} {algor_with_par gost2012_512:A}} {
+       global OPENSSL_CONF
+       if {![string length $CAname]} {
+               set CAname [file rootname [file tail $::argv0]]CA-2012
+       }       
+       set test::ca $CAname
+       file delete -force $CAname
+       file mkdir $CAname
+       makeFile $CAname/ca.conf "
+\[ ca \]
+default_ca      = CA_default            # The default ca section
+
+\[ CA_default \]
+
+dir            = [file join [pwd] $CAname]              # top dir
+database       = \$dir/index.txt        # index file.
+new_certs_dir  = \$dir/newcerts         # new certs dir
+
+certificate    = \$dir/cacert.pem       # The CA cert
+serial         = \$dir/serial           # serial no file
+private_key    = \$dir/private/cakey.pem# CA private key
+RANDFILE       = \$dir/private/.rand    # random number file
+
+default_days   = 3650                  # how long to certify for
+default_crl_days= 30                   # how long before next CRL
+default_md     = default               # use digest corresponding the algorithm
+default_startdate = 060101000000Z
+
+policy         = policy_any            # default policy
+email_in_dn    = yes                   #  add the email into cert D
+
+
+nameopt        = ca_default            # Subject name display option
+certopt        = ca_default            # Certificate display option
+copy_extensions = copy                 # Copy extensions from requ
+
+
+\[ policy_any \]
+countryName            = supplied
+stateOrProvinceName    = optional
+organizationName       = optional
+organizationalUnitName = optional
+commonName             = supplied
+emailAddress           = supplied
+
+"      
+       makeFile $CAname/req.conf "
+\[req\]
+prompt=no
+distinguished_name = req_dn
+\[ req_dn \]
+C = RU
+L = Moscow
+CN=Test CA $algor_with_par
+O=Cryptocom
+OU=OpenSSL CA
+emailAddress = openssl@cryptocom.ru
+"
+       file mkdir $CAname/private
+       file mkdir $CAname/newcerts
+       generate_key [keygen_params $algor_with_par] $CAname/private/cakey.pem
+       openssl "req -new  -x509 -key $CAname/private/cakey.pem -nodes -out $CAname/cacert.pem -config $CAname/req.conf -set_serial 0x11E"
+       makeFile ./$CAname/.rand 1234567890
+       makeFile ./$CAname/serial 011E
+       makeFile ./$CAname/index.txt ""
+       return [file isfile $CAname/cacert.pem]
+}
+
+proc extract_oids {filename {format PEM} {offset 0}} {
+       set out ""
+       if {$offset} {
+               set miscargs "-offset $offset "
+       } else {
+               set miscargs ""
+       }       
+       foreach line [split [openssl "asn1parse $miscargs-in $filename -inform $format -oid oidfile"] "\n"] {
+               if {([regexp {Gost\d+} $line]||[regexp "GostR" $line]||[regexp "GOST" $line]||[regexp "sha1" $line]) && ![regexp ^Loaded: $line]} {
+                       regsub {[^:]+:[^:]+:} $line "" line
+                       append out $line "\n"
+               }
+       }
+       return $out
+}
+# 
+# Формирует список параметров для openssl req необходимый для формирования 
+# ключа c указанным алгоритмом и параметрами
+#  
+proc keygen_params {alg} {     
+       return [split $alg :] 
+}      
+
+proc generate_key {params filename} {
+       set alg [lindex $params 0]
+       set param [lindex $params 1]
+       set keyname $alg
+       set keyname [append keyname _ $param .pem] 
+       switch -glob $alg {
+       rsa { 
+               if {![string length $param]} {
+                       set param 1024
+                       set keyname "rsa_1024.pem"
+               }
+               set optname "-algorithm rsa -pkeyopt rsa_keygen_bits:$param"
+               }
+       ec {set optname "-paramfile $param"}
+       dsa {set optname "-paramfile $param" }
+       gost* { set optname "-algorithm $alg -pkeyopt paramset:$param" }
+       }       
+       if {$::tcl_platform(platform) eq "windows"} {
+               set exesuffix ".exe"
+       } else {
+               set exesuffix ""
+       }
+       log "Keyname is $keyname"
+#      if {[engine_name] eq "open"} {
+               log "Calling openssl cmd to create private key"
+               openssl "genpkey  $optname -out $filename"
+#      } elseif {[info exists ::env(OBJ)] && [file executable ../$::env(OBJ)/keytest$exesuffix]&& $alg eq "gost2001"} {
+#              log "keytest$exesuffix $alg $param $filename"
+#              exec ../$::env(OBJ)/keytest$exesuffix $alg $param $filename >&@ stdout
+#      } elseif {[info exists ::env(OBJ)] && [file executable ../$::env(OBJ)/keytest$exesuffix]&& $alg eq "gost2012_256"} {
+#              log "keytest$exesuffix $alg $param $filename"
+#              exec ../$::env(OBJ)/keytest$exesuffix $alg $param $filename >&@ stdout
+#      } elseif {[info exists ::env(OBJ)] && [file executable ../$::env(OBJ)/keytest$exesuffix]&& $alg eq "gost2012_512"} {
+#              log "keytest$exesuffix $alg $param $filename"
+#              exec ../$::env(OBJ)/keytest$exesuffix $alg $param $filename >&@ stdout
+#      } elseif {[info exists ::env(PRIVATEKEYSDIR)] && [file exists $::env(PRIVATEKEYSDIR)/$keyname]} {
+#              log "Copying file $keyname"
+#              file copy $::env(PRIVATEKEYSDIR)/$keyname $filename
+#      } else {
+#              log "Calling openssl cmd to create private key"
+#              openssl "genpkey  $optname -out $filename"
+#      }
+}
+
+#
+# Создает тестового пользователя с одним ключом подписи и одной заявкой
+# на сертификат. 
+# Параметры 
+# username Имя директории, куда складывать файлы этого пользователя
+# alg Параметр для опции -newkey команды openssl req, задающий алгоритм
+#  ключа и параметры этого алгоритма
+# Последующие параметры имеют вид списка ключ значение и задают поля
+# Distinguished Name 
+# FIXME Процедуру надо поправить, чтобы работала с новой версией openssl
+proc makeUser {username alg args} {
+       file delete -force $username
+       file mkdir $username
+       if {[lsearch $args CN]==-1} {
+               lappend args CN $username
+       }       
+       makeFile $username/req.conf [eval makeConf $args]
+       log "req.conf --------\n[getFile $username/req.conf]-------------"
+       
+       generate_key [keygen_params $alg] $username/seckey.pem
+       openssl "req -new -key $username/seckey.pem -nodes -out $username/req.pem -config $username/req.conf"
+       return [expr {[file size $username/req.pem] > 0}]
+}
+
+proc makeSecretKey {username alg} {
+       file delete -force $username
+       file mkdir $username
+       generate_key [keygen_params $alg] $username/seckey.pem  
+       return [expr {[file size $username/seckey.pem] > 0}]
+}
+
+#
+# Создает пользователя с помощью makeUser и подписывает его сертификат
+# ключом ранее созданного testCA. 
+# Параметр CAname обрабатывается специальным образом: он не попадает в DN
+#
+proc makeRegisteredUser {username alg args } {
+       if {![info exists params(CAname)]&&![info exists ::test::ca]} {
+               return -code error "Default CA name is not known. Have you called makeCA earlier in this script?"
+       }       
+       set CAname $test::ca
+       array set params $args
+       if {[info exist params(CAname)]} {
+               set CAname $params(CAname)
+               unset params(CAname)
+       }
+       if {![file isdirectory $CAname]||![file exists $CAname/cacert.pem]} {
+               return -code error "CA $CAname doesn't exists"
+       }       
+       eval makeUser [list $username $alg] [array get params]
+       openssl "ca -config $CAname/ca.conf -in $username/req.pem -out $username/cert.pem -batch -notext" 
+       return [file isfile $username/cert.pem]
+}
+
+proc makeConf {args} {
+       global OPENSSL_CONF
+       array set dn_attrs [list C  RU\
+       L  Moscow\
+       CN "Dummy user"\
+       O Cryptocom\
+       OU "OpenSSL Team"\
+       emailAddress  "openssl@cryptocom.ru"\
+       ]
+       array set dn_attrs $args
+       if {[info exists dn_attrs(extensions)]} {
+               set extensions $dn_attrs(extensions)
+               unset dn_attrs(extensions)
+       }       
+       set out ""
+       append out {[req]
+prompt=no
+distinguished_name = req_dn
+}
+if {[info exists extensions]} {
+       append out "req_extensions = req_exts\n\[ req_exts \]\n" $extensions "\n"
+}      
+append out "\[ req_dn \]\n"
+       foreach {key val} [array get dn_attrs] {
+               append out "$key=$val\n"
+       }
+       return $out
+}      
+#
+# Выполняет замену регулярного выражения re на строку s в указанном
+# PEM-документе.
+#
+proc hackPem {re pem s} {
+       set out ""
+       foreach {whole_pem start_line coded_body end_line} [regexp -inline -all "(-----BEGIN \[^\n\]+-----\n)(.*?)(\n-----END \[^\n\]+-----\n)" $pem] {
+               set der [::base64::decode $coded_body]
+               set der [regsub -all $re $der $s]
+               append out $start_line [::base64::encode $der] $end_line
+       }
+       return $out
+}      
+
+#
+# Handling of OIDs
+#
+
+source [file dirname  [info script]]/name2oid.tcl
+foreach {name oid} [array get name2oid] {
+       set oid2name($oid) $name
+}
+
+proc long_name_by_id {id} {
+       variable name2oid
+       variable oid2name
+       if {[regexp {^\d+(\.\d+)+$} $id]} {
+       return "GOST $oid2name($id) $id"
+       }
+       return "GOST $id $name2oid($id)"
+}
+
+proc alg_id {alg} {
+       switch -glob $alg {
+               gost94cc {return pk_sign94_cc}
+               gost94cc:* {return pk_sign94_cc}
+               gost94:* {return pk_sign94_cp}
+               gost2001cc:* {return pk_sign01_cc}
+               gost2001cc {return pk_sign01_cc}
+               gost2001:* {return pk_sign01_cp}
+               gost2012_256:* {return pk_sign12_256}
+               gost2012_512:* {return pk_sign12_512}
+       }
+}
+
+proc alg_with_digest {alg} {
+       variable name2oid
+       switch -glob $alg {
+               gost94cc {return hash_with_sign94_cc}
+               gost94cc:* {return hash_with_sign94_cc}
+               gost94:* {return hash_with_sign94_cp}
+               gost2001cc:* {return hash_with_sign01_cc}
+               gost2001cc {return hash_with_sign01_cc}
+               gost2001:* {return hash_with_sign01_cp}
+               gost2012_256:* {return hash_with_sign12_256}
+               gost2012_512:* {return hash_with_sign12_512}
+               
+       }
+}
+
+proc alg_long_name {alg} {
+       variable name2oid
+       switch -glob $alg {
+               #gost94cc {return hash_with_sign94_cc}
+               #gost94cc:* {return hash_with_sign94_cc}
+               #gost94:* {return hash_with_sign94_cp}
+               #gost2001cc:* {return hash_with_sign01_cc}
+               #gost2001cc {return hash_with_sign01_cc}
+               gost2001:* {return "GOST R 34.10-2001"}
+               gost2012_256:* {return "GOST R 34.10-2012 with 256 bit modulus"}
+               gost2012_512:* {return "GOST R 34.10-2012 with 512 bit modulus"}
+       }
+}
+
+# Returns hash algorithm corresponded to sign algorithm
+proc alg_hash {alg} {
+    switch -glob $alg {
+        gost2012_256:* {return hash_12_256}
+        gost2012_512:* {return hash_12_512}
+        * {return hash_94}
+   }
+}
+
+# Returns short name of hash algorithm
+proc hash_short_name {hash_alg} {
+    switch -glob $hash_alg {
+        *hash_94 {return md_gost94}
+        hash_12_256 {return md_gost12_256}
+        hash_12_512 {return md_gost12_512}
+        default {return $hash_alg}
+    }
+}
+
+proc ts_hash_long_name {hash_alg} {
+    switch -glob $hash_alg {
+        *hash_94 {return md_gost94}
+        hash_12_256 {return md_gost12_256}
+        hash_12_512 {return md_gost12_512}
+        default {return $hash_alg}
+    }
+}
+
+# Returns long name of hash algorithm
+proc hash_long_name {hash_alg} {
+    switch -glob $hash_alg {
+               *hash_94* {return "GOST R 34.11-94"}
+               gost2001* {return "GOST R 34.11-94"}
+        *12_256* {return "GOST R 34.11-2012 with 256 bit hash"}
+        *12_512* {return "GOST R 34.11-2012 with 512 bit hash"}
+        default {return $hash_alg}
+    }
+}
+
+# Returns long name of hash_with_sign algorithm
+proc hash_with_sign_long_name {alg} {
+    switch -glob $alg {
+        gost2001:* {return "GOST R 34.11-94 with GOST R 34.10-2001"}
+        gost2012_256:* {return "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)"}
+        gost2012_512:* {return "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)"}
+        default {return $alg}
+    }
+}
+
+proc smime_hash_with_sign_long_name {alg} {
+    switch -glob $alg {
+        hash_with_sign01_cp {return "GOST R 34.11-94 with GOST R 34.10-2001"}
+        hash_with_sign12_256 {return "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)"}
+        hash_with_sign12_512 {return "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)"}
+        default {return $alg}
+    }
+}
+
+proc micalg {hash_alg} {
+    switch -exact $hash_alg {
+        hash_94 {return "gostr3411-94"}
+        hash_12_256 {return "gostr3411-2012-256"}
+        hash_12_512 {return "gostr3411-2012-512"}
+    }
+}
+
+proc param_pubkey {alg} {
+       variable name2oid
+       switch -exact $alg {
+               gost94cc: {return param_pubkey94_cpa}
+               gost94cc {return param_pubkey94_cpa}
+               gost94:A {return param_pubkey94_cpa}
+               gost94:B {return param_pubkey94_cpb}
+               gost94:C {return param_pubkey94_cpc}
+               gost94:D {return param_pubkey94_cpd}
+               gost94:XA {return param_pubkey94_cpxcha}
+               gost94:XB {return param_pubkey94_cpxchb}
+               gost94:XC {return param_pubkey94_cpxchc}
+               gost2001cc: {return param_pubkey01_cc}
+               gost2001cc {return param_pubkey01_cc}
+               gost2001:0 {return param_pubkey01_cptest}
+               gost2001:A {return param_pubkey01_cpa}
+               gost2001:B {return param_pubkey01_cpb}
+               gost2001:C {return param_pubkey01_cpc}
+               gost2001:XA {return param_pubkey01_cpxcha}
+               gost2001:XB {return param_pubkey01_cpxchb}
+               gost2012_256:0 {return param_pubkey01_cptest}
+               gost2012_256:A {return param_pubkey01_cpa}
+               gost2012_256:B {return param_pubkey01_cpb}
+               gost2012_256:C {return param_pubkey01_cpc}
+               gost2012_256:XA {return param_pubkey01_cpxcha}
+               gost2012_256:XB {return param_pubkey01_cpxchb}
+               gost2012_512:0 {return param_pubkey12_512_0}
+               gost2012_512:A {return param_pubkey12_512_A}
+               gost2012_512:B {return param_pubkey12_512_B}
+       }
+}
+
+
+proc param_hash_long_name {hash_alg} {
+    switch -glob $hash_alg {
+        *hash_94 {return "id-GostR3411-94-CryptoProParamSet"}
+        hash_12_256 {return "GOST R 34.11-2012 with 256 bit hash"}
+        hash_12_512 {return "GOST R 34.11-2012 with 512 bit hash"}
+    }
+}
+
+proc pubkey_long_name {alg} {
+       variable name2oid
+       switch -glob $alg {
+               
+               #gost2001cc: {return param_pubkey01_cc}
+               #gost2001cc {return param_pubkey01_cc}
+               #gost2001:0 {return param_pubkey01_cptest}
+               gost2001:A {return "id-GostR3410-2001-CryptoPro-A-ParamSet"}
+               gost2001:B {return "id-GostR3410-2001-CryptoPro-B-ParamSet"}
+               gost2001:C {return "id-GostR3410-2001-CryptoPro-C-ParamSet"}
+               gost2001:XA {return "id-GostR3410-2001-CryptoPro-XchA-ParamSet"}
+               gost2001:XB {return "id-GostR3410-2001-CryptoPro-XchB-ParamSet"}
+               #gost2012_256:0 {return param_pubkey01_cptest}
+               gost2012_256:A {return "id-GostR3410-2001-CryptoPro-A-ParamSet"}
+               gost2012_256:B {return "id-GostR3410-2001-CryptoPro-B-ParamSet"}
+               gost2012_256:C {return "id-GostR3410-2001-CryptoPro-C-ParamSet"}
+               gost2012_256:XA {return "id-GostR3410-2001-CryptoPro-XchA-ParamSet"}
+               gost2012_256:XB {return "id-GostR3410-2001-CryptoPro-XchB-ParamSet"}
+               #gost2012_512:0 {return param_pubkey12_512_0}
+               gost2012_512:A {return  "GOST R 34.10-2012 (512 bit) ParamSet A"}
+               gost2012_512:B {return  "GOST R 34.10-2012 (512 bit) ParamSet B"}
+       }
+}
+
+
+
+proc mkObjList {args} {
+       set out ""
+       foreach name $args {
+               append out " OBJECT            :$name\n"
+       }
+       return $out
+}
+
+proc structured_obj_list {args} {
+       variable name2oid
+       set out {}
+       foreach {path name} $args {
+               if {$name != {}} {set oid $name2oid($name)} {set oid {}}
+               lappend out "$path=$oid"
+       }
+       return $out
+}
+
+proc param_hash {alg} {
+    switch -glob $alg {
+        gost2012_256:* {return hash_12_256}
+        gost2012_512:* {return hash_12_512}
+        * {return param_hash_94}
+    }
+}
+
+
+proc param_encr {short_name} {
+       variable name2oid
+       if {[regexp {^\d+(\.\d+)+$} $short_name]} {
+       return "$short_name"
+       }
+       switch -exact $short_name {
+               cc_cipher_param {return param_encr_cc}
+               {} {return param_encr_tc}
+               cp_cipher_param_a {return param_encr_cpa}
+               cp_cipher_param_b {return param_encr_cpb}
+               cp_cipher_param_c {return param_encr_cpc}
+               cp_cipher_param_d {return param_encr_cpd}
+       }
+}
+
+proc encr_long_name {short_name} {
+       variable name2oid
+       switch -exact $short_name {
+               "1.2.643.2.2.31.1" {return "id-Gost28147-89-CryptoPro-A-ParamSet"}
+               "1.2.643.2.2.31.2" {return "id-Gost28147-89-CryptoPro-B-ParamSet"}
+               "1.2.643.2.2.31.3" {return "id-Gost28147-89-CryptoPro-C-ParamSet"}
+               "1.2.643.2.2.31.4" {return "id-Gost28147-89-CryptoPro-D-ParamSet"}
+               "1.2.643.7.1.2.5.1.1" {return "GOST 28147-89 TC26 parameter set"}
+               {} {return "GOST 28147-89 TC26 parameter set"}
+       }
+}
+
+
+
+#
+# Функции для управления клиентом и сервером при тестировании
+# SSL-соединения
+#
+
+#  Параметры
+#    Список аргументов командной строки клиента
+#    список аргументов командной строки сервера
+#    строка, которую надо передать на stdin клиенту
+#
+# Запускает openssl s_server и пытается приконнектиться к нему openssl
+# s_client-ом. Возвращает список stdout  клиента, stderr клиента, кода
+# завершения клиента, stdout
+# сервера stderr сервера и кода завершения сервера.
+# 
+# Если процесс убит сигналом, возвращает в качестве кода завершения имя
+# сигнала, иначе - числовое значение кода завершения ОС
+# 
+proc client_server {client_args server_args client_stdin} {
+       log "CLIENT ARGS\n$client_args\n"
+       log "SERVER ARGS\n$server_args\n"
+       flush [test_log]
+       set server [open_server $server_args]
+       set client [open_client $client_args $client_stdin]
+       log "server = $server client = $client"
+       log "Both client and server started"
+       flush [test_log]
+       global finished
+       log "Waitng for client to termintate"
+       flush [test_log]
+#      if {$::tcl_platform(platform) == "windows"} {
+#              exec ../kbstrike [pid $client] 0x20
+#      }
+       vwait finished($client) 
+       catch {stop_server $server}
+       set list [concat [stop $client] [stop $server]]
+       foreach channel {"CLIENT STDOUT" "CLIENT STDERR" "CLIENT EXIT CODE"  "SERVER STDOUT"
+       "SERVER STDERR" "SERVER EXIT CODE"} data $list {
+               log "$channel\n$data\n"
+       }
+       return $list
+}
+#
+# Устанавливает командную строку для вызова клиента,
+# в системный openssl на указанном хосте
+#
+proc remote_client {host} {
+       if {[info hostname] == "$host"} {
+               set ::test::client_unset {OPENSSL_CONF}
+               set ::test::client_app "openssl s_client"
+       } else {
+               set ::test::client_unset {LD_LIBRARY_PATH OPENSSL_CONF}
+               set ::test::client_app "ssh build@$host openssl s_client"
+       }
+}      
+#
+# Устанавливает командную строку для вызова клиента в указанную команду
+# Необязательный параметр указывает список переменных окружения, которые
+# НЕ НАДО передавать в эту команду
+#
+proc custom_client {command {forbidden_vars {}}} {
+       set ::test::client_app $command
+       set ::test::client_unset $forbidden_vars
+
+}
+#
+# Восстанавливает станадртую клиентскую команду
+#
+proc our_client {} {
+       catch {unset ::test::client_app}
+       catch {unset ::test::client_unset}
+}      
+
+#
+# Закрывает файл, указанный в соответствующем file_id, возвращает
+# элемент глобального массива output, содержимое error message от close
+# и код завершения процесса (имя сигнала)
+proc stop {file_id} {
+       global output
+       fconfigure $file_id -blocking yes
+       if {[catch {close $file_id} msg]} {
+               if {[string match CHILD* [lindex $::errorCode 0]]} {
+                       set status [lindex $::errorCode 2]
+               } else {
+                       set status 0
+               }       
+       }  else {
+               set status 0
+       }       
+       return [list $output($file_id) $msg $status]
+}      
+#
+# Завершает работу сервера
+#
+proc stop_server {file_id} {
+#      puts $file_id "Q\n" 
+#      catch {set xx [socket localhost 4433]}
+       log "Interrupting process [pid $file_id]"
+       flush [test_log]
+       kill INT [pid $file_id]
+       #puts -nonewline stderr "Waiting for server termination.."
+       vwait finished($file_id)
+       if [info exists xx] {close $xx}
+#      puts stderr "Ok"
+}      
+
+#
+# Запускает процесс с указанной командной строкой. Возвращает дескриптор
+# файла в nonblocking mode с повешенным туда fileevent
+# Очищает соответствующие элементы массивов output и finished
+proc start_process {cmd_line read_event {mode "r"}} {
+       set f [open "|$cmd_line" $mode]
+       global output finished
+       catch {unset finished($f)}
+       fconfigure $f -buffering none -blocking n
+       set output($f) ""
+       fileevent $f readable [list $read_event $f]
+       return $f
+}      
+#
+# Обработчик fileevent-ов на чтение. Записывает считанные данные в
+# элемент массива output соответствущий файлхендлу. В случае если
+# достигнут eof, выставляет элемент массива finished. (элемент output
+# при этом тоже трогается, чтобы vwait завершился)
+#
+proc process_read {f} {
+       global output
+       if {[eof $f]} {
+               global finished
+               fconfigure $f -blocking y
+               set finished($f) 1
+               append output($f) ""
+               return
+       }       
+       append output($f) [read $f]
+}      
+
+#
+#  Запускает openssl s_server с указанными аргументами и дожидается пока
+#  он скажет на stdout ACCEPT. Возвращает filehandle, открытый на
+#  чтение/запись
+#
+proc open_server {server_args} {
+       global OPENSSL_APP
+       global ENGINE_PATH
+       if {[info exists ::test::server_conf]} {
+               global env
+               set save_conf $env(OPENSSL_CONF)
+               set env(OPENSSL_CONF) $::test::server_conf
+       }
+       if {[info exists ::test::server_app]} {
+               set server $::test::server_app
+       } else {
+               set server [list $OPENSSL_APP s_server]
+       }
+       if {[info exists ::test::server_unset]} {
+               save_env $::test::server_unset
+       }       
+       set server [start_process [concat $server $server_args] process_read "r+"]
+       restore_env
+       if {[info exists save_conf]} {
+               set env(OPENSSL_CONF) $save_conf
+       }       
+
+       global output finished
+       #puts -nonewline stderr  "Waiting for server startup..."
+       while {![regexp "\nACCEPT\n" $output($server)]} {
+               vwait output($server)
+               if {[info exists finished($server)]} {
+                       #puts stderr "error"
+                       return -code error [lindex  [stop $server] 1]
+               }       
+       }               
+       #puts stderr "Ok"
+       after 100
+       return $server
+}
+#
+# Сохраняет указанные переменные среды для последующего восстановления
+# restore_env
+#
+proc save_env {var_list} {
+       catch {array unset ::test::save_env}
+       foreach var $var_list {
+               if {[info exist ::env($var)]} {
+                       set ::test::save_env($var) $::env($var)
+                       unset ::env($var)
+               }       
+       }
+
+}
+proc restore_env {} {
+       if {[array exists ::test::save_env]} {
+               array set ::env [array get ::test::save_env]
+               array unset ::test::save_env
+       }       
+       
+}
+#
+# Сохраняет указанные переменные среды для последующего восстановления
+# restore_env2. В отличие от save_env, не делает unset сохраненной переменной.
+#
+proc save_env2 {var_list} {
+       catch {array unset ::test::save_env2}
+       foreach var $var_list {
+               if {[info exist ::env($var)]} {
+                       set ::test::save_env2($var) $::env($var)
+               }       
+       }
+
+}
+#
+# Восстанавливает переменные среды, ранее сохраненные функцией save_env2 
+# В отличие от функции restore_env, требует списка переменных и 
+# восстанавливает только переменные из данного списка. Второе отличие -
+# если переменная из списка не была сохранена, делает ей unset.
+#
+proc restore_env2 {var_list} {
+       foreach var $var_list {
+               if {[info exist ::test::save_env2($var)]} {
+                       set ::env($var) $::test::save_env2($var)
+               } else {
+                       catch {unset ::env($var)}
+               }
+       }
+       array unset ::test::save_env2
+}
+
+
+#
+# Запускает s_client с указанными аргументами, передавая на stdin
+# указанную строку
+#
+proc open_client {client_args client_stdin} {
+       global OPENSSL_APP
+       if [info exists ::test::client_app] {
+               set client $::test::client_app
+       } else {
+               set client [list $OPENSSL_APP s_client]
+       }
+       if {[info exists ::test::client_unset]} {
+               save_env $::test::client_unset
+       }       
+       if {[info exists ::test::client_conf]}  {
+               set save_env(OPENSSL_CONF) $::env(OPENSSL_CONF)
+               set ::env(OPENSSL_CONF) $::test::client_conf
+       }
+       set client [start_process [concat $client $client_args [list << $client_stdin]] process_read]
+       restore_env
+       return $client
+}      
+#
+# Зачитывает список хостов из ../../ssl-ciphers
+#
+proc get_hosts {file} {
+       set ::test::suffix "-$file"
+       if [file readable $file.ciphers] {
+               set f [open $file.ciphers]
+       } else {        
+               set f [open ../../ssl-ciphers/$file.ciphers r]
+       }
+       while {[gets $f line]>=0} {
+               if {[regexp {^\s*#} $line]} continue
+               append data "$line\n"
+       }
+       close $f
+       global hosts
+       array set hosts $data
+}      
+#
+# Регистрирует пользователся (возможно удаленном) тестовом CA, используя
+# скрипт testca установленный в PATH на CAhost.
+#
+
+proc registerUserAtCA {userdir CAhost CAprefix CApath} {
+               global OPENSSL_APP
+               log "registerUserAtCA $userdir $CAhost $CAprefix $CApath"
+               set f [open  $userdir/req.pem]
+               set request [read $f]
+               close $f
+               set token [::http::geturl http://$CAhost/$CAprefix/$CApath\
+               -query [::http::formatQuery request $request startdate [clock\
+               format [expr [clock seconds]-3600] -format "%y%m%d%H%M%SZ" -gmt y]]]
+               if {[::http::ncode $token]!=200} {
+                       return -code error "Error certifying request [::http::data $token]"
+               }
+               log "Got a certificate. Saving"
+               saveCertFromPKCS7 $userdir/cert.pem [::http::data $token]
+}
+proc saveCertFromPKCS7 {file pkcs7} {
+               global OPENSSL_APP
+               log saveCertFromPCS7
+               log "$OPENSSL_APP pkcs7 -print_certs $pkcs7"
+               set f [open "|[list $OPENSSL_APP pkcs7 -print_certs << $pkcs7]" r]
+               set out [open $file w]
+               set mode 0
+               while {[gets $f line]>=0} {
+                       if {$mode==1} {
+                               puts $out $line
+                               if {$line eq "-----END CERTIFICATE-----"} {
+                                       set mode 2
+                               }
+                       } elseif {$mode==0 && $line eq "-----BEGIN CERTIFICATE-----"} {
+                               set mode 1
+                               puts $out $line
+                       }
+               }       
+               close $f
+               close $out
+               if {$mode !=2 } {
+                       return -code error "Cannot get certificate from PKCS7 output"
+               }       
+}
+#
+# Invokes scp and discards stderr output if exit code is 0
+#
+proc scp {args} {
+       if {[info exists env(SCP)]} {
+               set scp $env(SCP)
+       } else {
+               set scp scp
+       }       
+       if {[catch [concat exec $scp $args] msg]} {
+               if {[string match CHIDLD* [lindex $::errorCode 0]]} {
+                       return -code error -errorcode $::errorCode  $msg
+               }
+       }
+}      
+
+proc getCAAlgParams {CAhost CAprefix alg} {
+       if {$alg == "ec" || $alg == "dsa"} {
+               set token [::http::geturl http://$CAhost/$CAprefix/$alg?algparams=1]
+               if {[::http::ncode $token]!=200} {
+                       return -code error "Error getting algorithm parameters [::http::data $token]"
+               }
+               set f [open ${alg}params.pem w]
+               puts $f [::http::data $token]
+               close $f
+       }
+}      
+#
+# Copies CA certificate from specified CA into ca_$alg.pem
+# Returns name of the ca certificate or empty line if something goes
+# wrong and error wasn't properly detected
+#
+proc getCAcert {CAhost CApath alg} {
+       set token [::http::geturl http://$CAhost$CApath/$alg?getroot=1]
+       if {[::http::ncode $token]!=200} {
+               return -code error "Error getting root cert for $alg: [::http::data $token]"
+       }
+       saveCertFromPKCS7 ca_$alg.pem [::http::data $token]     
+       return ca_$alg.pem
+}
+#
+# Returns decoded version of first pem object in the given file
+#
+proc readpem {filename} {
+       set f [open $filename]
+       fconfigure $f -translation binary
+       set data [read $f]
+       close $f
+       if {[regexp -- "-----BEGIN \[^\n\]+-----\r?\n(.*\n)-----END" $data => b64]} {
+               set data [::base64::decode $b64]
+       }  
+       return $data
+
+}
+       
+proc der_from_pem {pem} {
+       if {[regexp -- {^-----BEGIN ([^\n]*)-----\r?\n(.*)\r?\n-----END \1-----} $pem => => base64]} {
+               ::base64::decode $base64
+       } {
+               error "Not a PEM:\n$pem"
+       }
+}
+
+proc engine_name {} {
+       global env
+       if {[info exists env(ENGINE_NAME)]} {
+               switch -exact $env(ENGINE_NAME) {
+                       "open" {return "open"}
+                       "gost" {return "open"}
+                       "cryptocom" {return "ccore"}
+                       "ccore" {return "ccore"}
+                       default {error "Unknown engine '$env(ENGINE_NAME)'"}
+               }
+       } else {
+               return "ccore"
+       }
+}
+
+proc openssl_remote {files host cmdlinex suffix} {
+               set hostname [exec hostname]
+               set workpath /tmp/$hostname/$suffix
+               save_env {LD_LIBRARY_PATH OPENSSL_CONF ENGINE_DIR}
+               exec ssh build@$host mkdir -p $workpath
+               foreach file $files {
+                       exec scp -r $file build@$host:$workpath
+               }
+               exec scp ../opnssl.sh build@$host:$workpath
+               exec ssh build@$host chmod +x $workpath/opnssl.sh
+               set cmdline [string map "TESTPATH $workpath" $cmdlinex]
+               log "hstname: $hostname OpenSSL cmdline: $host remote_openssl $cmdline"
+               set f [open "| ssh build@$host $workpath/opnssl.sh $cmdline" r]
+               set output [read $f]
+               restore_env
+               if {[catch {close $f} msg]} {
+                       append output "STDERR CONTENTS:\n$msg"
+                       log $output
+                       if {[lindex $::errorCode 0]!="NONE"} {
+                               return -code error -errorcode $::errorCode $output
+                       }
+               }
+               return $output
+}
+
+package provide ossltest 0.7
diff --git a/tcl_tests/pkcs12.try b/tcl_tests/pkcs12.try
new file mode 100644 (file)
index 0000000..52e23d6
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+
+start_tests "Тесты на команду pkcs12" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2001:XA gost2001:XB gost2012_256:A gost2012_256:B gost2012_256:C gost2012_256:XA gost2012_256:XB gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2001:XA gost2001:XB gost2012_256:B gost2012_256:C gost2012_256:XA gost2012_256:XB gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_pkcs12_$alg_fn
+       switch -glob $alg {
+               gost2012_512:* {set hash_alg md_gost12_512}
+               gost2012_256:* {set hash_alg md_gost12_256}
+               default {set hash_alg md_gost94}
+       }
+       
+test -createsfiles [list $username/sscert.pem $username/sskey.pem]\
+  "Генерируем сертификат и секретный ключ $alg" {
+       makeSecretKey $username $alg
+       makeFile $username/req.conf [makeConf]
+       openssl "req -new -x509 -config $username/req.conf -key $username/seckey.pem -out $username/cert.pem"   
+       expr {[file size $username/cert.pem] > 0}
+} 0 1
+
+test -createsfiles {$username/pkcs12.p12} "Собираем pkcs12 с алгоритмом $alg" {
+       openssl "pkcs12 -export -inkey $username/seckey.pem -in $username/cert.pem -out $username/pkcs12.p12 -password pass:12345 -keypbe gost89 -certpbe gost89 -macalg $hash_alg"
+       file exists $username/pkcs12.p12
+} 0 1
+
+test -skip {![file exists $username/pkcs12.p12]} -createsfiles [list $username/extracted_cert.pem $username/extracted_key.pem] "Разбираем pkcs12 c алгоритмом $alg" {
+       openssl "pkcs12 -in $username/pkcs12.p12 -nodes -out $username/dump.pem -password pass:12345"
+       set dump [getFile $username/dump.pem]
+       set lextr [regexp -all -inline "\n-----BEGIN .*?\n-----END \[^\n\]+-----\n" $dump]
+       
+       list [llength $lextr] [expr {[lindex $lextr 0] eq "\n[getFile $username/cert.pem]"}] [expr {[lindex $lextr 1] eq "\n[openssl "pkcs8 -nocrypt -topk8 -in $username/seckey.pem"]"}]    
+       
+} 0 {2 1 1}
+
+
+#./load_engine pkcs12 -export -in t/z/U_enc_gost94_/cert.pem -inkey t/z/U_enc_gost94_/seckey.pem -certfile t/z/testCA/cacert.pem -name "CERTIFICATE" -out mycert.p12 -password pass:12345
+#./load_engine pkcs12 -in mycert.p12 -out mycert.pem 
+
+}
+
+end_tests
diff --git a/tcl_tests/pkcs7.tcl b/tcl_tests/pkcs7.tcl
new file mode 100644 (file)
index 0000000..4e9d134
--- /dev/null
@@ -0,0 +1,187 @@
+package require base64
+if {[info exists env(TOOLDIR)]} {
+       lappend auto_path $env(TOOLDIR)
+} {
+       lappend auto_path "[file dirname [info script]]/../../maketool"
+}
+package require asn 0.7.1
+
+namespace eval pkcs7 {
+       namespace import ::asn::*
+       namespace export *
+
+       proc asnTag {data_var} {
+               upvar $data_var data
+               asnPeekByte data b
+               return $b
+       }
+
+       proc envelopedData {der} {
+               asnGetSequence der seq0
+               asnGetObjectIdentifier seq0 id_envelopedData
+               if {$id_envelopedData != {1 2 840 113549 1 7 3}} {
+                       error "Waited id-envelopedData, got $id_envelopedData"
+               }
+               asnGetContext seq0 n envelopedData
+               if {$n != 0} {
+                       error "Waited context 0, got $n"
+               }
+               asnGetSequence envelopedData envelopedData
+               asnGetInteger envelopedData version
+               set originatorInfo {}
+               if {[asnTag envelopedData] != 0x31} {
+                       asnGetContext envelopedData tag originatorInfo
+               }
+               asnGetSet envelopedData recipientInfos
+               asnGetSequence envelopedData encryptedContentInfo
+               set unprotectedAttrs {}
+               if {[string length $envelopedData]} {
+                       asnGetContext envelopedData tag unprotectedAttrs
+               }
+               return [list $version $originatorInfo $recipientInfos $encryptedContentInfo $unprotectedAttrs $envelopedData]
+       }
+
+       proc recipientInfos {rIs} {
+               set result {}
+               while {[string length $rIs]} {
+                       asnGetSequence rIs inf
+                       asnGetInteger inf version
+                       set tag {}
+                       if {[asnTag inf] == 0x30} {
+                               asnGetSequence inf rid
+                       } {
+                               asnGetContext inf tag rid
+                       }
+                       asnGetSequence inf keyEncAlg
+                       asnGetOctetString inf encryptedKey
+                       lappend result [list $version [list $tag $rid] $keyEncAlg $encryptedKey]
+               }
+               return $result
+       }
+
+       proc subjectPublicKeyInfo {spki} {
+               asnGetSequence spki algorithmIdentifier
+               asnGetBitString spki subjectPublicKey
+               list $algorithmIdentifier $subjectPublicKey $spki
+       }
+
+       proc algorithmIdentifier {ai} {
+               asnGetObjectIdentifier ai oid
+               set param {}
+               if {[string length $ai]} {
+                       asnGetSequence ai param
+               }
+               return [list $oid $param $ai]
+       }
+
+       proc algorithmParamPKGOST {param} {
+               asnGetObjectIdentifier param pubkey_param
+               asnGetObjectIdentifier param digest_param
+               set cipher_param {}
+               if {[string length $param]} {
+                       asnGetObjectIdentifier param cipher_param
+               }
+               return [list $pubkey_param $digest_param $cipher_param $param]
+       }
+
+       proc keyTransportGOST {octet_string} {
+               asnGetSequence octet_string inf
+               asnGetSequence inf encryptedKey
+               set transportParams {}
+               if {[string length $inf]} {
+                       asnGetContext inf tag transportParams
+               }
+               return [list $encryptedKey $transportParams $inf]
+       }
+
+       proc encryptedKeyGOST {encryptedKeyAndMAC} {
+               asnGetOctetString encryptedKeyAndMAC encryptedKey
+               asnGetOctetString encryptedKeyAndMAC MAC
+               list $encryptedKey $MAC $encryptedKeyAndMAC
+       }
+
+       proc transportParameters {transportParams} {
+               asnGetObjectIdentifier transportParams encryptionParamSet
+               set ephemeralPublicKey {}
+               if {[asnTag transportParams] == 0xa0} {
+                       asnGetContext transportParams tag ephemeralPublicKey
+               }
+               asnGetOctetString transportParams ukm
+               list $encryptionParamSet $ephemeralPublicKey $ukm $transportParams
+       }
+
+       proc encryptedContentInfo {eci} {
+               asnGetObjectIdentifier eci oid
+               asnGetSequence eci algorithmIdentifier
+               set encryptedContent {}
+               if {[string length $eci]} {
+                       asnGetContext eci tag encryptedContent
+               }
+               list $oid $algorithmIdentifier $encryptedContent $eci
+       }
+
+       proc algorithmParamEncGOST {param} {
+               asnGetOctetString param ukm
+               asnGetObjectIdentifier param encParam
+               list $ukm $encParam $param
+       }
+
+       proc algorithm_oids_from_envelopedData {der} {
+               set result {}
+               foreach {v oI rIs eCI uAs t} [envelopedData $der] {
+                       # recipient infos
+                       set rin 0
+                       foreach rI [recipientInfos $rIs] {
+                               foreach {v rid kEA eK} $rI {
+                                       # export (pubkey) algorithm identifier
+                                       foreach {pk_oid param t} [algorithmIdentifier $kEA] {
+                                               lappend result ri${rin}:kea=[join $pk_oid .]
+                                               foreach {pkp dp cp t} [algorithmParamPKGOST $param] {
+                                                       lappend result \
+                                                               ri${rin}:kea:pkp=[join $pkp .] \
+                                                               ri${rin}:kea:dp=[join $dp .] \
+                                                               ri${rin}:kea:cp=[join $cp .]
+                                               }
+                                       }
+                                       # encryptedKey encapsulated structure
+                                       foreach {eK tPs t} [keyTransportGOST $eK] {
+                                               # transport parameters
+                                               foreach {ePS ePK ukm t} [transportParameters $tPs] {
+                                                       # encryption paramset
+                                                       lappend result ri${rin}:ktcp=[join $ePS .]
+                                                       # ephemeral public key
+                                                       if {[string length $ePK]} {
+                                                               foreach {aI sPK t} [subjectPublicKeyInfo $ePK] {
+                                                                       # algorithm identifier
+                                                                       foreach {pKI param t} [algorithmIdentifier $aI] {
+                                                                               lappend result ri${rin}:ktepk=[join $pKI .]
+                                                                               foreach {pkp dp cp t} [algorithmParamPKGOST $param] {
+                                                                                       lappend result \
+                                                                                               ri${rin}:ktepk:pkp=[join $pkp .] \
+                                                                                               ri${rin}:ktepk:dp=[join $dp .] \
+                                                                                               ri${rin}:ktepk:cp=[join $cp .]
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               incr rin
+                       }
+                       foreach {oid aI eC t} [encryptedContentInfo $eCI] {
+                               # algorithm identifier
+                               foreach {oid param t} [algorithmIdentifier $aI] {
+                                       lappend result ea=[join $oid .]
+                                       foreach {ukm oid t} [algorithmParamEncGOST $param] {
+                                               lappend result ea:cp=[join $oid .]
+                                       }
+                               }
+                       }
+               }
+               return $result
+       }
+
+}
+
+package provide pkcs7 0.1
\ No newline at end of file
diff --git a/tcl_tests/pkcs8.try b/tcl_tests/pkcs8.try
new file mode 100644 (file)
index 0000000..ce742c7
--- /dev/null
@@ -0,0 +1,170 @@
+#!/usr/bin/tclsh
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "тесты на команду pkcs8" 
+set key "-----BEGIN PRIVATE KEY-----
+MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgIgSZ82qYpu6RQj
+UeoKl5svrvYuMriHeAQvuSIvjAg5fnk=
+-----END PRIVATE KEY-----
+"
+
+test "Печатаем эталонный ключ gost2001" {
+       set etalon [openssl [list pkey -text -noout << $key]]
+} 0 "Private key: 499F36A98A6EE9142351EA0A979B2FAEF62E32B88778042FB9222F8C08397E79
+Parameter set: id-GostR3410-2001-CryptoPro-A-ParamSet
+"
+
+test "Конвертируем в DER и проверяем, что ключ тот же gost2001" {
+       openssl [list pkcs8 -outform DER -out pkcs8-1.der -nocrypt << $key]
+       openssl [list pkey -inform DER -text -noout -in pkcs8-1.der]
+} 0 $etalon
+
+
+save_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+test "Зашифровываем незашифрованный ключ gost2001, параметры CryptoPro-A" {
+       makeFile pkcs8-1A.key $key
+       set env(CRYPT_PARAMS) "id-Gost28147-89-CryptoPro-A-ParamSet"
+       set env(GOST_PBE_HMAC) "md_gost94"
+       openssl [list pkcs8 -v2 gost89 -passout pass:qwertyu -in pkcs8-1A.key -topk8 -out encA.key << $key]
+       file exists encA.key
+} 0 1
+restore_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+       
+test -skip {![file exists encA.key]} "Проверяем OID-ы PBE" {
+       set res [extract_oids encA.key]
+       regexp "HMAC GOST 34\.11-94" $res && regexp "GOST .*89"
+} 0 1
+
+test "Расшифровываем зашифрованный ключ gost2001" {
+       set unencrypted [openssl [list pkcs8 -passin pass:qwertyu -topk8 -nocrypt -in encA.key]]
+       openssl [list pkey -text -noout << $unencrypted]
+       
+} 0 $etalon
+
+save_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+test "Зашифровываем незашифрованный ключ gost2001, параметры CryptoPro-B" {
+       makeFile pkcs8-1B.key $key
+       set env(CRYPT_PARAMS) "id-Gost28147-89-CryptoPro-B-ParamSet"
+       set env(GOST_PBE_HMAC) "md_gost94"
+       openssl [list pkcs8 -v2 gost89 -passout pass:qwertyu -in pkcs8-1B.key -topk8 -out encB.key << $key]
+       file exists encB.key
+} 0 1
+restore_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+       
+test -skip {![file exists encB.key]} "Проверяем OID-ы PBE" {
+       set res [extract_oids encB.key]
+       regexp "HMAC GOST 34\.11-94" $res && regexp "GOST .*89"
+} 0 1
+
+
+test "Расшифровываем зашифрованный ключ gost2001" {
+       set unencrypted [openssl [list pkcs8 -passin pass:qwertyu -topk8 -nocrypt -in encB.key]]
+       openssl [list pkey -text -noout << $unencrypted]
+       
+} 0 $etalon
+
+
+test "Расшифровываем ключ, созданный mkkey" {
+       makeFile pkcs8-2.key "-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGvMFUGCSqGSIb3DQEFDTBIMCcGCSqGSIb3DQEFDDAaBAjIvbrnGmGbTAIC
+CAAwCgYGKoUDAgIKBQAwHQYGKoUDAgIVMBMECOtWtCMQo3dzBgcqhQMCAh8B
+BFZFPKP6qDKi57rmas1U2fUjyZwjmrk6Y+naeWG/BTVJNJklW3HaHP+wuIFb
+bxdi6rTNsYqxWm26qUHz6Op5SvCm0y+f8zE9cACQ5KQnFvNlojHvzmjO+Q==
+-----END ENCRYPTED PRIVATE KEY-----
+"
+       set unencrypted [openssl [list pkcs8 -passin pass:qwertyu -nocrypt -topk8 -in pkcs8-2.key ]]
+       openssl [list pkey -text -noout << $unencrypted]
+} 0 $etalon
+
+test "Расшифровываем ключ, созданный mkkey, русский пароль" {
+       set env(PASS) [encoding convertfrom [encoding convertto utf-8 [rus "йцукенг"]]]
+       makeFile pkcs8-3.key "-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGvMFUGCSqGSIb3DQEFDTBIMCcGCSqGSIb3DQEFDDAaBAgSfbLQ+fNe0AIC
+CAAwCgYGKoUDAgIKBQAwHQYGKoUDAgIVMBMECJJ1Qd/rIBxqBgcqhQMCAh8B
+BFZWfyFs12456ECvzNyg7LkPNAJS7qPih78kY4DJP7ty4bMydfCkfg20fMNl
+O2zlJtg37z9vbhvqdWODCXc/XJ+Txmw3GLVDcvwQ/0woebcPlNUvMd9BzA==
+-----END ENCRYPTED PRIVATE KEY-----
+"
+       set unencrypted [openssl [list pkcs8 -passin env:PASS -nocrypt -topk8 -in pkcs8-3.key ]]
+       grep Private [openssl [list pkey -text -noout << $unencrypted]]
+} 0 "Private key: 894150BCD66A400C198154D68E5817A6EF3546983863B57F6D04F5C14FD766CC\n"
+
+set key256 "-----BEGIN PRIVATE KEY-----
+MEgCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEIgIgK/ezK4Z5
+GCo/srftX/HPs2AmcFKffF3/RWokTAKxMcM=
+-----END PRIVATE KEY-----
+"
+
+test "Печатаем эталонный ключ gost2012_256" {
+       set etalon256 [openssl [list pkey -text -noout << $key256]]
+} 0 "Private key: 2BF7B32B8679182A3FB2B7ED5FF1CFB3602670529F7C5DFF456A244C02B131C3
+Parameter set: id-GostR3410-2001-CryptoPro-A-ParamSet
+"
+
+test "Конвертируем в DER и проверяем, что ключ тот же gost2012_256" {
+       openssl [list pkcs8 -outform DER -out pkcs8-256.der -nocrypt << $key]
+       openssl [list pkey -inform DER -text -noout -in pkcs8-256.der]
+} 0 $etalon
+
+save_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+test "Зашифровываем незашифрованный ключ gost2012_256, параметры TK26 (умолчательные)" {
+       makeFile pkcs8-256.key $key256
+       catch {unset env(CRYPT_PARAMS)}
+       catch {unset env(GOST_PBE_HMAC)}
+       openssl [list pkcs8 -v2 gost89 -passout pass:qwertyu -in pkcs8-256.key -topk8 -out enc256.key << $key]
+       file exists enc256.key
+} 0 1
+restore_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+       
+test -skip {![file exists enc256.key]} "Проверяем OID-ы PBE" {
+       set res [extract_oids enc256.key]
+       regexp "HMAC GOST 34\.11-2012" $res && regexp "GOST .*89"
+} 0 1
+
+test "Расшифровываем зашифрованный ключ gost2012_256" {
+       set unencrypted [openssl [list pkcs8 -passin pass:qwertyu -topk8 -nocrypt -in enc256.key]]
+       openssl [list pkey -text -noout << $unencrypted]
+       
+} 0 $etalon256
+
+set key512 "-----BEGIN PRIVATE KEY-----
+MGsCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRDAkEAiCjF
+2rwOmb5YwNnyObveusCDO+kw33jBijSrPiye155EO4ABz2aG8SHOTObVv4dFgtfZ
+g7wCuOZN3D6RSByFJA==
+-----END PRIVATE KEY-----
+"
+
+save_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+test "Печатаем эталонный ключ gost2012_512" {
+       set etalon512 [openssl [list pkey -text -noout << $key512]]
+} 0 "Private key: 8828C5DABC0E99BE58C0D9F239BBDEBAC0833BE930DF78C18A34AB3E2C9ED79E443B8001CF6686F121CE4CE6D5BF874582D7D983BC02B8E64DDC3E91481C8524
+Parameter set: GOST R 34.10-2012 (512 bit) ParamSet A
+"
+
+test "Конвертируем в DER и проверяем, что ключ тот же gost2012_512" {
+       openssl [list pkcs8 -outform DER -out pkcs8-512.der -nocrypt << $key]
+       openssl [list pkey -inform DER -text -noout -in pkcs8-512.der]
+} 0 $etalon
+
+test "Зашифровываем незашифрованный ключ gost2012_512, параметры TK26 (умолчательные)" {
+       makeFile pkcs8-512.key $key512
+       catch {unset env(CRYPT_PARAMS)}
+       set env(GOST_PBE_HMAC) "md_gost12_512"
+       openssl [list pkcs8 -v2 gost89 -passout pass:qwertyu -in pkcs8-512.key -topk8 -out enc512.key << $key]
+       file exists enc512.key
+} 0 1
+restore_env2 {CRYPT_PARAMS GOST_PBE_HMAC}
+       
+test -skip {![file exists enc512.key]} "Проверяем OID-ы PBE" {
+       set res [extract_oids enc512.key]
+       regexp "HMAC GOST 34\.11-2012" $res && regexp "GOST .*89"
+} 0 1
+
+test "Расшифровываем зашифрованный ключ gost2012 512 bit" {
+       set unencrypted [openssl [list pkcs8 -passin pass:qwertyu -topk8 -nocrypt -in enc512.key]]
+       openssl [list pkey -text -noout << $unencrypted]
+       
+} 0 $etalon512
+
+end_tests
diff --git a/tcl_tests/pkgIndex.tcl b/tcl_tests/pkgIndex.tcl
new file mode 100644 (file)
index 0000000..f4a3345
--- /dev/null
@@ -0,0 +1,6 @@
+package ifneeded test 0.2 [list source [file join $dir test.tcl]]
+package ifneeded testlib 0.1 [list source [file join $dir testlib.tcl]]
+package ifneeded fgetopt 0.1 [list source [file join $dir fgetopt.tcl]]
+package ifneeded asn 0.7.1 [list source [file join $dir asn.tcl]]
+package ifneeded base64 2.3.2 [list source [file join $dir base64.tcl]]
+package ifneeded ossltest 0.7 [list source [file join $dir ossltest.tcl]]
diff --git a/tcl_tests/plain.enc b/tcl_tests/plain.enc
new file mode 100644 (file)
index 0000000..2dd9652
--- /dev/null
@@ -0,0 +1 @@
+Test data to encrypt 
\ No newline at end of file
diff --git a/tcl_tests/private/gost2001_A.pem b/tcl_tests/private/gost2001_A.pem
new file mode 100644 (file)
index 0000000..73eeef2
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQgNsz+6JQm0UYw
+I90/psShKQrktCj3ehyKe3G7dVuo+ySgODA2BggqhQMCCQMIATEqBChCIIzvjjnM
+EjW957oYXmI1tlNIIEMFy50EOPk4d/akd8k9UEUfJQ31
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2001_B.pem b/tcl_tests/private/gost2001_B.pem
new file mode 100644 (file)
index 0000000..cf8dd4c
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwICHgEEIgQgvVb0e4AmOEIH
+jKiZj+29OgbFVwy+XHI48yKm8FJyjQygODA2BggqhQMCCQMIATEqBCh3mHOU3GbN
+IZuseCRP836vV2rBLOuQrVznWHPOb9VC0lB6eNOhY1GH
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2001_C.pem b/tcl_tests/private/gost2001_C.pem
new file mode 100644 (file)
index 0000000..b8dc57c
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwMGByqFAwICHgEEIgQgbIM6LxPe0Ave
+N+yRZBsb7jmIyZET+YiWpiN3T4sKGiOgODA2BggqhQMCCQMIATEqBCgftKdkhEXD
+VG50lrUkn9EbqriBTKRO8SK2Yu9VJfeVt9uDpYQ9dMu2
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2001_XA.pem b/tcl_tests/private/gost2001_XA.pem
new file mode 100644 (file)
index 0000000..8884bd2
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIgQgSGtJ/s0X+5ld
+2wilev1VMOVYAiYPqxJeBCovJlnsB3agODA2BggqhQMCCQMIATEqBChquxeySqNx
+XJ+zRfoydNB3ZnI7WHvyCdevrpnUXi43QfJ7Bofldn7G
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2001_XB.pem b/tcl_tests/private/gost2001_XB.pem
new file mode 100644 (file)
index 0000000..a94b9aa
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwICHgEEIgQgYAQQC17Sjt3F
+rg9m7PyzD9Pa2eAYTMr8ltX3IBOmukWgODA2BggqhQMCCQMIATEqBCgl8zuE43h4
+78dfpVXoV7bD85G2SIY1/d7o+bAr8AiQBumvzlnQr2ka
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_256_A.pem b/tcl_tests/private/gost2012_256_A.pem
new file mode 100644 (file)
index 0000000..5f13bb8
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwEGCCqFAwcBAQICBCIEIOTjkLas
+e0/SvSH/hFRSfBopnkP9a6mqCqP/zEf6WwFsoDgwNgYIKoUDAgkDCAExKgQoXql/
+cWe/7Tgh3csptrfiEgAaWgGS+VhzbJnZLvn9/STU1/46KWA+0A==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_256_B.pem b/tcl_tests/private/gost2012_256_B.pem
new file mode 100644 (file)
index 0000000..2e7c6d2
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwIGCCqFAwcBAQICBCIEIO6zQc6w
+YqWlSTp4BBlVa3q+6w96tRtpWlp+LZjb5ShyoDgwNgYIKoUDAgkDCAExKgQotOvO
+EGwCt0ZcyZA+Lq3RwctxfJMIImyY48X/UilpdLTbfuxNTrAP7Q==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_256_C.pem b/tcl_tests/private/gost2012_256_C.pem
new file mode 100644 (file)
index 0000000..7ed1a14
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwMGCCqFAwcBAQICBCIEIAmU+PyI
+r/n63dlQoJhZu0NNJgay2KEFmtb2JvDsLDtzoDgwNgYIKoUDAgkDCAExKgQoTmXk
+7VWKAP0WNGF3y26CldydpwA1llejlnI3eZ0IaIq6In4K3SzWjw==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_256_XA.pem b/tcl_tests/private/gost2012_256_XA.pem
new file mode 100644 (file)
index 0000000..e32ce8a
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICJAAGCCqFAwcBAQICBCIEIAlnokn7
+Vw8a7IykYa4EYlv6zdit8QG5Fxs9wdWF/LuyoDgwNgYIKoUDAgkDCAExKgQopAxM
+Ymu/ufjc2DAxKwaMaeI1cQbNZGApKGrBgFr5/azc+wYpkV/tIg==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_256_XB.pem b/tcl_tests/private/gost2012_256_XB.pem
new file mode 100644 (file)
index 0000000..aa2d421
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICJAEGCCqFAwcBAQICBCIEIB7ziMjS
+yZxVTj9kzt5nyHoz0BVpvWkb8dAxo5SjV9KBoDgwNgYIKoUDAgkDCAExKgQoM1Rx
+tOEXmeWQll3cuet7UDp0YEmVid1AMvvdx3MD4LVthAmrIYKUCg==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_512_A.pem b/tcl_tests/private/gost2012_512_A.pem
new file mode 100644 (file)
index 0000000..fe04189
--- /dev/null
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGkAgEAMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAQYIKoUDBwEBAgMEQgRAdBFk
+9bJa60Rw9jvTNdtfZ3ImZuep2Klx5Fpap1bpBE4u/T4CI/R2nyjuWCBKPmbBHJO7
+4Z/BTUYYe04l0gWWZaA4MDYGCCqFAwIJAwgBMSoEKCHK4j/oPjNmh1w4eH6Zx1cQ
+kzLi1QCYb8u45IFtpBx0jF4O0etcYKo=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/gost2012_512_B.pem b/tcl_tests/private/gost2012_512_B.pem
new file mode 100644 (file)
index 0000000..e59abff
--- /dev/null
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGkAgEAMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAgYIKoUDBwEBAgMEQgRAQ8Hd
+iGVmLyWQFF7lR2VnBIV/npcxJOTrsdhnSpNczZVT+ZWEvY66IQMsUPCVUcgZIYyp
+44E3v8kD6x0EuCmPcqA4MDYGCCqFAwIJAwgBMSoEKG0+06BM69y0EvoCeE4fP8jB
+XPhDcF9daMRu299ZaXv2H9o/OO+nC5A=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/private/rsa_1024.pem b/tcl_tests/private/rsa_1024.pem
new file mode 100644 (file)
index 0000000..2db01ec
--- /dev/null
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANiP17PGKutiabuB
+HCtGk5sBn/4Sv/X7d2HQBDwpxKx0t8U7Z+hRtzLLCRCyNiY+vnbGHkQKfAi/HfaA
+awvG9mGBBOA5jdRU0c9aJUNEHH4I/EkYzEkWxZHTNTVbZM4CUHJvA7AM8kRXyI00
+MTKirF0/clTXaiAryhprioSw0ulxAgMBAAECgYEAr5ch3D/neOdYt5Gd13DoKZyN
+ryJgxv/X8lUJugZb00Dn6GGchIANPH/nn8P/p87j+8XzsFOX8jeUAdRp9yihhzuN
+doY8EW0UEKXApHh5Y0UmlC1YqFrgtk8Y6k4bK6GewNXPekMjTLUhR+cECG6I8yAt
+Jtlwo+539uBld6pXEAECQQDuH6IrLZHXfxTYOeDnvYnncKrfk7szUTRV/2q8GAlw
+1bqQPB1xuautWrgw90HRLAvD27KOFgZ0R9fNfULaEA3xAkEA6NHTsZNgZs7VF5Z8
+krR6SkszIyR3UyurvPrusR44lT6ypSsulFV+SrjFOAwbuLjl+fap9oGLI1tsbFUA
+UeMTgQJAKrX71XjP/vIpX/tJruddU+jujTmnSzYWiBJPJ7u7/cQoOXS+50YhV++8
+t/Oxl34qAhBm/3tN3w9/0rjUA977UQJAWLHvKvxRQnlTVvwekyksWXdSkPXIe6fs
+cj9KhbFUrw7GsgPEaAA177N6dsKuIO5XtqWQ1Hc/kYW3xYGQcKHIgQJBAIaEvBhO
+PkoT0apaZgriQnuWpqGCnFYTjAY7zSr+Y5kI1lnb3DPipIsZZ5X7VQ/c+64nR2M/
+X1NAW+G8zHBxK6o=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/req-genpkey.try b/tcl_tests/req-genpkey.try
new file mode 100644 (file)
index 0000000..e333dc0
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+# создание секретного ключа
+# создание заявки и самоподписанного сертификата командой req
+# проверка OIDов алгоритма во всех структурах
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Создание ключей и заявок, команда genpkey"
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2001:XA gost2001:XB gost2012_256:A gost2012_256:B gost2012_256:C gost2012_256:XA gost2012_256:XB gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2001:XA gost2001:XB gost2012_256:0 gost2012_256:A gost2012_256:B gost2012_256:C gost2012_256:XA gost2012_256:XB gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username pkey_$alg_fn
+       foreach {alg_only params} [split $alg :] break
+
+test -createsfiles $username/seckey.pem "Секретный ключ, алгоритм $alg" {
+       file delete -force $username
+       file mkdir $username
+       openssl "genpkey -algorithm $alg_only -pkeyopt paramset:$params -out $username/seckey.pem"
+       expr {[file size $username/seckey.pem] > 0}
+} 0 1
+
+test -skip {![file exists $username/seckey.pem]} "OID в секретном ключе" {
+       extract_oids $username/seckey.pem
+} 0 [mkObjList [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]]]
+
+test -skip {![file exists $username/seckey.pem]} "Алгоритм $alg, заявка по секретному ключу" {
+       makeFile $username/req.conf [makeConf]
+       openssl "req -new -config $username/req.conf -key $username/seckey.pem -out $username/req.pem"  
+       expr {[file size $username/req.pem] > 0}
+} 0 1
+
+test -skip {![file exists $username/req.pem]} "Подпись под заявкой корректна" {
+       grep "verif" [openssl "req -verify -in $username/req.pem"]
+} 0 {verify OK
+}
+
+test -skip {![file exists $username/req.pem]} "OID в заявке, алгоритм $alg" {
+       extract_oids $username/req.pem
+} 0 [mkObjList [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [hash_with_sign_long_name $alg]]
+
+test -skip {![file exists $username/seckey.pem]} "Алгоритм $alg, сертификат по секретному ключу" {
+       openssl "req -new -x509 -config $username/req.conf -key $username/seckey.pem -out $username/cert.pem"   
+       expr {[file size $username/cert.pem] > 0}
+} 0 1
+
+test -skip {![file exists $username/cert.pem]} "OID в сертификате" {
+       extract_oids $username/cert.pem
+} 0 [mkObjList  [hash_with_sign_long_name $alg] [alg_long_name $alg] [pubkey_long_name $alg]\
+ [param_hash_long_name [param_hash $alg]] [hash_with_sign_long_name $alg]]
+
+test -createsfiles "$username/seckey.der"  "Алгоритм $alg сохраняем ключ в DER-формате" {
+       openssl "genpkey -algorithm $alg_only -pkeyopt paramset:$params -out $username/seckey.der -outform DER"
+       file exists $username/seckey.der
+} 0 1
+
+test -skip {![file exists $username/seckey.der]} "OID в секретном ключе $alg DER" {
+       extract_oids $username/seckey.der DER
+} 0 [mkObjList [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]]]
+
+test -skip {![file exists $username/seckey.der]} -createsfiles $username/req2.pem "Создаем заявку из ключа в формате DER" {
+       openssl "req -new  -config $username/req.conf -key $username/seckey.der -keyform der  -out $username/req2.pem"  
+       expr {[file size $username/req2.pem] > 0}
+} 0 1
+
+test -skip {![file exists $username/req2.pem]} "Подпись под заявкой корректна" {
+       grep "verif" [openssl "req -verify -in $username/req2.pem"]
+} 0 {verify OK
+}
+
+}
+
+
+end_tests
diff --git a/tcl_tests/req-newkey.try b/tcl_tests/req-newkey.try
new file mode 100644 (file)
index 0000000..fe05fa6
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+if {[info exists env(PKG_PATH)]} {
+       lappend auto_path $env(PKG_PATH)
+} else {       
+       lappend auto_path [file dirname [info script]]
+}
+package require ossltest
+package require asn 0.4.1
+cd $::test::dir
+
+switch -exact [engine_name] {
+       "ccore" {
+               set no_param_set "no public key parameters set"
+               set invalid_paramset "invalid pubic key paramset name"
+       }
+       "open" {
+               set no_param_set "no parameters set"
+               set invalid_paramset "parameter error"
+       }
+}
+
+start_tests "Создание ключей и заявок, команда req -newkey"
+makeCA
+foreach {alg descr code result} {
+gost2001: "ГОСТ 2001 Криптопро" 1 no_param_set
+gost2001:A "ГОСТ 2001 Криптопро A" 0 1.2.643.2.2.35.1
+gost2001:B "ГОСТ 2001 Криптопро B" 0 1.2.643.2.2.35.2
+gost2001:C "ГОСТ 2001 Криптопро C" 0 1.2.643.2.2.35.3
+gost2001:D "ГОСТ 2001 Криптопро неверный параметр" 1 invalid_paramset
+gost2001:test "ГОСТ 2001 Криптопро тестовый" 0 1.2.643.2.2.35.0
+gost2001:XA "ГОСТ 2001 Криптопро XA" 0 1.2.643.2.2.36.0
+gost2001:XB "ГОСТ 2001 Криптопро XB" 0 1.2.643.2.2.36.1
+gost2001:id-GostR3410-2001-CryptoPro-XchB-ParamSet  "ГОСТ 2001 Криптопро XB по имени" 0 1.2.643.2.2.36.1
+gost2001:1.2.643.2.2.36.1 "ГОСТ 2001 Криптопро XB по OID" 0 1.2.643.2.2.36.1
+gost2001:1.2.840.113549.1.1.1 "Недопустимый OID" 1 invalid_paramset
+gost2001:RSAencryption: "Недопустимое имя объекта" 1 invalid_paramset
+gost2012_256: "ГОСТ 2012 256 бит" 1 no_param_set
+gost2012_256:A "ГОСТ 2012 256 бит Криптопро A" 0 1.2.643.2.2.35.1
+gost2012_256:B "ГОСТ 2012 256 бит Криптопро B" 0 1.2.643.2.2.35.2
+gost2012_256:C "ГОСТ 2012 256 бит Криптопро C" 0 1.2.643.2.2.35.3
+gost2012_256:D "ГОСТ 2012 256 бит Криптопро неверный параметр" 1 invalid_paramset
+gost2012_256:id-GostR3410-2001-CryptoPro-B-ParamSet  "ГОСТ 2012 256 бит Криптопро B по имени" 0 1.2.643.2.2.35.2
+gost2012_256:1.2.643.2.2.35.1 "ГОСТ 2012 256 бит Криптопро A по OID" 0 1.2.643.2.2.35.1
+gost2012_256:1.2.840.113549.1.1.1 "Недопустимый OID" 1 invalid_paramset
+gost2012_256:RSAencryption: "Недопустимое имя объекта" 1 invalid_paramset
+gost2012_512: "ГОСТ 2012 512 бит" 1 no_param_set
+gost2012_512:A "ГОСТ 2012 512 бит ТК26 A" 0 1.2.643.7.1.2.1.2.1
+gost2012_512:B "ГОСТ 2012 512 бит ТК26 B" 0 1.2.643.7.1.2.1.2.2
+gost2012_512:C "ГОСТ 2012 512 бит неверный параметр" 1 invalid_paramset
+gost2012_512:id-tc26-gost-3410-2012-512-paramSetB  "ГОСТ 2012 512 бит набор параметров B по имени" 0 1.2.643.7.1.2.1.2.2
+gost2012_512:1.2.643.7.1.2.1.2.1 "ГОСТ 2012 512 бит набор параметров A по OID" 0 1.2.643.7.1.2.1.2.1
+gost2012_512:1.2.643.2.2.35.1 "Недопустимый OID" 1 invalid_paramset
+gost2012_512:RSAencryption: "Недопустимое имя объекта" 1 invalid_paramset
+
+
+} {
+
+       switch -exact $result {
+               "no_param_set" { set result $no_param_set }
+               "invalid_paramset" { set result $invalid_paramset }
+       }
+       
+       set index [string first ":" $alg]
+       if {$index != -1} {
+               set algname [string range $alg 0 [expr $index-1]]
+               set algparam [string range $alg [expr $index+1] end]
+       } else {
+               set algname $alg
+               set algparam ""
+       }
+       if {$algparam ne ""} {
+               set algparamcmdline "-pkeyopt paramset:$algparam"
+       } else {
+               set algparamcmdline ""
+       }
+
+       test -skip {{[engine_name] eq "open" && $alg eq "gost2001:test"}} $descr {
+               openssl "req -newkey $algname $algparamcmdline -keyout test.key -out test.req -batch -nodes -config $::test::ca/req.conf"
+               set pkcs8 [readpem test.key]
+               asn::asnGetSequence pkcs8 seq1
+               asn::asnGetInteger seq1 int0
+               asn::asnGetSequence seq1 seq2
+               asn::asnGetObjectIdentifier seq2 oid
+               asn::asnGetSequence seq2 seq3
+               asn::asnGetObjectIdentifier seq3 oid
+               join $oid .
+       } $code $result 
+       log "errorInfo: $errorInfo"
+
+       test -skip {![file exists test.req]} "Заявка подписана корректно" {
+               grep "verif" [openssl "req -verify -in test.req"]
+       } 0 "verify OK\n"
+}
+end_tests
diff --git a/tcl_tests/runtest.bat b/tcl_tests/runtest.bat
new file mode 100755 (executable)
index 0000000..68da053
--- /dev/null
@@ -0,0 +1,88 @@
+@echo off\r
+\r
+rem Тесты на коммерческий энжин выполняются с тем ДСЧ, на использование \r
+rem которого сконфигурирован КриптоПакет (то есть который указан в файле \r
+rem конфигурации или переменной окружения RNG). Исключение - наборы тестов\r
+rem prng.try, rng.try, rng-seed.try (всегда тестируют ДСЧ PROGRAM) и \r
+rem rng2.try (тестирует все ДСЧ, которые найдет на компьютере). \r
+\r
+\r
+rem Состав набора тестов\r
+rem 1. Этот скрипт\r
+rem 2. Файлы *.try\r
+rem 3. Файлы *.tcl\r
+rem 4. Файлы *.ciphers\r
+rem 5. calcstat\r
+rem 6. oidfile\r
+rem 7. name2oid.tst\r
+\r
+rem Пререквизиты, которые должны быть установлены на машине:\r
+rem 1. tclsh.\r
+rem 2. ssh (что характерно, называться должен именно так и не должен выводить\r
+rem лишних сообщений), мы используем ssh.bat вокруг putty:\r
+rem @plink -l build %*\r
+rem Должен и настроен заход по ключам без пароля на lynx и все используемые\r
+rem эталонники. Ключи этих машин должны быть в knownhosts с полными доменными \r
+rem именами серверов, то есть lynx.lan.cryptocom.ru и т.д. (для putty \r
+rem knownhosts хранятся в реесте).\r
+rem В Firewall Windows необходимо прописать исключение, разрешающее \r
+rem соединения для программы openssl.exe. Внимание, Windows неправильно \r
+rem трактует понятие "локальная сеть" в описании исключения, нужно либо\r
+rem выставлять "любой компьютер", либо явно задавать маску 10.51.0.0/255.255.0.0\r
+\r
+\r
+IF "%OPENSSL_APP%"=="" set OPENSSL_APP=c:\cryptopack3\bin\openssl.exe\r
+IF "%TCLSH%"=="" set TCLSH=c:\Tcl\bin\tclsh.exe\r
+\r
+%TCLSH% getengine.tcl > engine_name.txt\r
+set /p ENGINE_NAME= < engine_name.txt\r
+del engine_name.txt\r
+\r
+hostname > host_name.txt\r
+set /p HOST_NAME= < host_name.txt\r
+del host_name.txt\r
+set TESTDIR=%HOST_NAME%-bat-%ENGINE_NAME%\r
+rmdir /s /q %TESTDIR%\r
+mkdir %TESTDIR%\r
+copy oidfile %TESTDIR%\r
+set OTHER_VERSION=../OtherVersion\r
+\r
+IF %ENGINE_NAME%==cryptocom (\r
+               set BASE_TESTS=engine dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts ssl smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-gost\r
+) ELSE (\r
+       IF %ENGINE_NAME%==gost (\r
+               set BASE_TESTS=engine dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts ssl smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-cryptocom\r
+       ) ELSE (\r
+               echo No GOST providing engine found\r
+               exit 1\r
+       )\r
+)\r
+\r
+set PKCS7_COMPATIBILITY_TESTS=smime_cs cmsenc_cs cmsenc_sc\r
+set CLIENT_TESTS=cp20 cp21\r
+set WINCLIENT_TESTS=p1-1xa-tls1-v-cp36r4-srv p1-1xa-tls1-v-cp39-srv p1-1xa-tls1-v-cp4-01 p2-1xa-tls1-v-cp4-01 p2-2xa-tls1-v-cp4-12S p2-5xa-tls1-v-cp4-12L p1-1xa-tls1-v-cp4r3-01 p2-1xa-tls1-v-cp4r3-01 p2-2xa-tls1-v-cp4r3-01 p2-5xa-tls1-v-cp4r3-01 p1-1xa-tls1_1-v-cp4r3-01 p2-1xa-tls1_1-v-cp4r3-01 p2-2xa-tls1_1-v-cp4r3-01 p2-5xa-tls1_1-v-cp4r3-01 p1-1xa-tls1_2-v-cp4r3-01 p2-1xa-tls1_2-v-cp4r3-01 p2-2xa-tls1_2-v-cp4r3-01 p2-5xa-tls1_2-v-cp4r3-01 p1-1xa-tls1-v-cp5-01 p2-1xa-tls1-v-cp5-01 p2-2xa-tls1-v-cp5-01 p2-5xa-tls1-v-cp5-01 p1-1xa-tls1_1-v-cp5-01 p2-1xa-tls1_1-v-cp5-01 p2-2xa-tls1_1-v-cp5-01 p2-5xa-tls1_1-v-cp5-01 p1-1xa-tls1_2-v-cp5-01 p2-1xa-tls1_2-v-cp5-01 p2-2xa-tls1_2-v-cp5-01 p2-5xa-tls1_2-v-cp5-01\r
+set SERVER_TESTS=cp20 cp21 csp36r4 csp39 csp4 csp4r3 csp5\r
+set OPENSSL_DEBUG_MEMORY=on\r
+\r
+FOR %%t IN (%BASE_TESTS%) DO %TCLSH% %%t.try\r
+FOR %%t IN (%PKCS7_COMPATIBILITY_TESTS%) DO %TCLSH% %%t.try\r
+FOR %%t IN (%SERVER_TESTS%) DO %TCLSH% server.try %%t\r
+FOR %%t IN (%CLIENT_TESTS%) DO %TCLSH% client.try %%t\r
+set CVS_RSH=ssh\r
+FOR %%t IN (%WINCLIENT_TESTS%) DO %TCLSH% wcli.try %%t\r
+IF EXIST %TESTDIR%\%OTHER_DIR% %TCLSH% interop.try\r
+IF EXIST %TESTDIR%\%OTHER_VERSION% (\r
+       set OTHER_DIR=%OTHER_VERSION%\r
+       IF %ENGINE_NAME%==cryptocom (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       ) ELSE (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       )\r
+       %TCLSH% interop.try\r
+)\r
+\r
+%TCLSH% calcstat %TESTDIR%\stats %TESTDIR%\test.result\r
diff --git a/tcl_tests/runtest.sh b/tcl_tests/runtest.sh
new file mode 100644 (file)
index 0000000..a59c946
--- /dev/null
@@ -0,0 +1,155 @@
+#!/bin/sh
+# -*- coding: cp1251 -*-
+
+# Состав набора тестов
+# 1. Этот скрипт
+# 2. Файлы *.try
+# 3. Файлы *.tcl
+# 4. Файлы *.ciphers
+# 5. calcstat
+# 6. oidfile
+# 7. name2oid.tst
+
+# Пререквизиты, которые должны быть установлены на машине:
+# 1. tclsh.  Может называться с версией (см. список версий ниже в цикле
+# перебора)
+# 2. ssh (что характерно, называться должен именно так). Должен быть 
+# настроен заход по ключам без пароля на lynx и все используемые эталонники.
+# Ключи этих машин должны быть в knownhosts (с полными доменными именами 
+# серверов, то есть lynx.lan.cryptocom.ru и т.д.)
+# 3. Под Windows скрипт выполняется в среде MinGW, при этом нужно "донастроить"
+# ssh, а именно создать в разделе реестра
+# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
+# DWORD-ключ DisableUserTOSSetting=0 
+
+CRYPTOPACK_MAIN_VERSION=3
+
+if [ -z "$OPENSSL_APP" ]; then
+       if [ "$OS" != "Windows NT" -a "$OS" != "Windows_NT" ]; then
+               if [ -x  /opt/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl ]; then
+                       OPENSSL_APP=/opt/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl
+               elif [ -x /usr/local/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl ];then
+                       OPENSSL_APP=/usr/local/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl
+               fi
+       else
+               if [ -x c:/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl.exe ] ; then
+                       OPENSSL_APP=c:/cryptopack$CRYPTOPACK_MAIN_VERSION/bin/openssl.exe
+               fi
+       fi
+fi
+if [ -z "$OPENSSL_APP" ]; then
+       echo "openssl not found"
+       exit 1
+else 
+       echo "Using $OPENSSL_APP as openssl"
+fi
+
+
+if [ -z "$TCLSH" ]; then
+       for version in "" 8.4 84 8.5 85 8.6 86; do
+               for command in tclsh$version; do
+                       for dir in `echo "/opt/cryptopack/bin:$PATH" | sed -e 's/:/ /g'`; do
+                               echo "Checking $dir/$command"
+                               if [ -x $dir/$command ]; then
+                                       TCLSH=$dir/$command
+                                       break 3
+                               fi
+                       done
+               done
+       done
+fi
+
+if [ -z "$TCLSH" ]; then
+       echo "tclsh not found in PATH, neither with nor without version, exiting"
+       exit 2
+else
+       echo "Using $TCLSH as tclsh"
+fi
+
+APP_SUFFIX=`basename $OPENSSL_APP .exe|sed s/openssl//`
+[ -n "$OPENSSL_APP" ]&& export OPENSSL_APP
+ENGINE_NAME=`$TCLSH getengine.tcl`
+export ENGINE_NAME
+TESTDIR=`hostname`-$ENGINE_NAME
+[ -n "$APP_SUFFIX" ] && TESTDIR=${TESTDIR}-${APP_SUFFIX}
+[ -d ${TESTDIR} ] && rm -rf ${TESTDIR}
+mkdir ${TESTDIR}
+cp oidfile ${TESTDIR}
+export TESTDIR
+
+case "$ENGINE_NAME" in
+       gostkc3)
+               BASE_TEST="1"
+               ;;
+       cryptocom)
+               BASE_TESTS="engine dgst mac pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts ssl smime_io cms_io smimeenc_io cmsenc_io"
+               OTHER_DIR=`echo $TESTDIR |sed 's/cryptocom/gost/'`
+               ;;
+       gost)
+               OTHER_DIR=`echo $TESTDIR |sed 's/gost/cryptocom/'`
+               ;;
+       *)
+               echo "No GOST=providing engine found" 1>&2
+               exit 1;
+esac
+if [ -x copy_param ];  then
+       BASE_TESTS="$BASE_TESTS apache"
+fi
+PKCS7_COMPATIBILITY_TESTS="smime_cs cmsenc_cs cmsenc_sc"
+SERVER_TESTS="cp20 cp21 csp36r4 csp39 csp4 csp4r3 csp5"
+CLIENT_TESTS="cp20 cp21"
+WINCLIENT_TESTS="p1-1xa-tls1-v-cp36r4-srv p1-1xa-tls1-v-cp39-srv p1-1xa-tls1-v-cp4-01 p2-1xa-tls1-v-cp4-01 p2-2xa-tls1-v-cp4-12S p2-5xa-tls1-v-cp4-12L p1-1xa-tls1-v-cp4r3-01 p2-1xa-tls1-v-cp4r3-01 p2-2xa-tls1-v-cp4r3-01 p2-5xa-tls1-v-cp4r3-01 p1-1xa-tls1_1-v-cp4r3-01 p2-1xa-tls1_1-v-cp4r3-01 p2-2xa-tls1_1-v-cp4r3-01 p2-5xa-tls1_1-v-cp4r3-01 p1-1xa-tls1_2-v-cp4r3-01 p2-1xa-tls1_2-v-cp4r3-01 p2-2xa-tls1_2-v-cp4r3-01 p2-5xa-tls1_2-v-cp4r3-01 p1-1xa-tls1-v-cp5-01 p2-1xa-tls1-v-cp5-01 p2-2xa-tls1-v-cp5-01 p2-5xa-tls1-v-cp5-01 p1-1xa-tls1_1-v-cp5-01 p2-1xa-tls1_1-v-cp5-01 p2-2xa-tls1_1-v-cp5-01 p2-5xa-tls1_1-v-cp5-01 p1-1xa-tls1_2-v-cp5-01 p2-1xa-tls1_2-v-cp5-01 p2-2xa-tls1_2-v-cp5-01 p2-5xa-tls1_2-v-cp5-01 p8k-5xa-tls1_2-v-cp5-01 p8k-2xa-tls1_2-v-cp5-01 p8m-5xa-tls1_2-v-cp5-01 p8m-2xa-tls1_2-v-cp5-01"
+OPENSSL_DEBUG_MEMORY=on
+export OPENSSL_DEBUG_MEMORY
+
+fail=0
+for t in $BASE_TESTS; do
+       $TCLSH $t.try || fail=1
+done
+
+ALG_LIST="rsa:1024 gost2001:XA gost2012_256:XA gost2012_512:A" OPENSSL_CONF=`pwd`/openssl-gost.cnf $TCLSH ssl.try -clientconf `pwd`/openssl-cryptocom.cnf || fail=1
+ALG_LIST="rsa:1024 gost2001:XA gost2012_256:XA gost2012_512:A" OPENSSL_CONF=`pwd`/openssl-gost.cnf $TCLSH ssl.try -serverconf `pwd`/openssl-cryptocom.cnf || fail=1
+       
+for t in $PKCS7_COMPATIBILITY_TESTS; do
+       $TCLSH $t.try || fail=1
+done
+for t in $SERVER_TESTS; do
+       $TCLSH server.try $t || fail=1
+done
+for t in $CLIENT_TESTS; do
+       $TCLSH client.try $t || fail=1
+done
+if [ -n "WINCLIENT_TESTS" ]; then
+       if [ -z "$CVS_RSH" ]; then
+               CVS_RSH=ssh
+               export CVS_RSH
+       fi      
+       for t in $WINCLIENT_TESTS; do
+               $TCLSH wcli.try $t || fail=1
+       done
+fi     
+if [ -d $OTHER_DIR ]; then
+       OTHER_DIR=../${OTHER_DIR} $TCLSH interop.try
+fi
+if [ -d OtherVersion ] ; then
+       case "$ENGINE_NAME" in
+               gostkc3)
+                       ;;
+               cryptocom)
+                       OTHER_DIR=../OtherVersion ALG_LIST="gost2001:A gost2001:B gost2001:C" ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:" $TCLSH interop.try
+                       ;;
+               gost)
+                       OTHER_DIR=../OtherVersion ALG_LIST="gost2001:A gost2001:B gost2001:C" ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:" $TCLSH interop.try
+                       ;;
+               *)
+                       echo "No GOST=providing engine found" 1>&2
+                       exit 1;
+       esac
+fi     
+$TCLSH calcstat ${TESTDIR}/stats ${TESTDIR}/test.result
+grep "leaked" ${TESTDIR}/*.log
+if [ $fail  -ne 0 ]; then 
+       echo "Some tests FAILED."
+fi     
+
+exit $fail
diff --git a/tcl_tests/runtest1.bat b/tcl_tests/runtest1.bat
new file mode 100755 (executable)
index 0000000..8986104
--- /dev/null
@@ -0,0 +1,81 @@
+@echo off\r
+\r
+rem Состав набора тестов\r
+rem 1. Этот скрипт\r
+rem 2. Файлы *.try\r
+rem 3. Файлы *.tcl\r
+rem 4. Файлы *.ciphers\r
+rem 5. calcstat\r
+rem 6. oidfile\r
+rem 7. name2oid.tst\r
+\r
+rem Пререквизиты, которые должны быть установлены на машине:\r
+rem 1. tclsh.\r
+rem 2. ssh (что характерно, называться должен именно так и не должен выводить\r
+rem лишних сообщений), мы используем ssh.bat вокруг putty:\r
+rem @plink -l build %*\r
+rem Должен и настроен заход по ключам без пароля на lynx и все используемые\r
+rem эталонники. Ключи этих машин должны быть в knownhosts с полными доменными \r
+rem именами серверов, то есть lynx.lan.cryptocom.ru и т.д. (для putty \r
+rem knownhosts хранятся в реесте).\r
+rem В Firewall Windows необходимо прописать исключение, разрешающее \r
+rem соединения для программы openssl.exe. Внимание, Windows неправильно \r
+rem трактует понятие "локальная сеть" в описании исключения, нужно либо\r
+rem выставлять "любой компьютер", либо явно задавать маску 10.51.0.0/255.255.0.0\r
+\r
+\r
+IF "%OPENSSL_APP%"=="" set OPENSSL_APP=c:\cryptopack3\bin\openssl.exe\r
+IF "%TCLSH%"=="" set TCLSH=c:\Tcl\bin\tclsh.exe\r
+\r
+%TCLSH% getengine.tcl > engine_name.txt\r
+set /p ENGINE_NAME= < engine_name.txt\r
+del engine_name.txt\r
+\r
+hostname > host_name.txt\r
+set /p HOST_NAME= < host_name.txt\r
+del host_name.txt\r
+set TESTDIR=%HOST_NAME%-bat-%ENGINE_NAME%\r
+rmdir /s /q %TESTDIR%\r
+mkdir %TESTDIR%\r
+copy oidfile %TESTDIR%\r
+set OTHER_VERSION=../OtherVersion\r
+\r
+IF %ENGINE_NAME%==cryptocom (\r
+               set BASE_TESTS=engine ssl dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-gost\r
+) ELSE (\r
+       IF %ENGINE_NAME%==gost (\r
+               set BASE_TESTS=engine dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts ssl smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-cryptocom\r
+       ) ELSE (\r
+               echo No GOST providing engine found\r
+               exit 1\r
+       )\r
+)\r
+\r
+set PKCS7_COMPATIBILITY_TESTS=smime_cs cmsenc_cs cmsenc_sc\r
+set CLIENT_TESTS=cp20 cp21\r
+set WINCLIENT_TESTS=p1-1xa-tls1-v-cp36r4-srv p1-1xa-tls1-v-cp39-srv p1-1xa-tls1-v-cp4-01 p2-1xa-tls1-v-cp4-01 p2-2xa-tls1-v-cp4-12S p2-5xa-tls1-v-cp4-12L p1-1xa-tls1-v-cp4r3-01 p2-1xa-tls1-v-cp4r3-01 p2-2xa-tls1-v-cp4r3-01 p2-5xa-tls1-v-cp4r3-01 p1-1xa-tls1_1-v-cp4r3-01 p2-1xa-tls1_1-v-cp4r3-01 p2-2xa-tls1_1-v-cp4r3-01 p2-5xa-tls1_1-v-cp4r3-01 p1-1xa-tls1_2-v-cp4r3-01 p2-1xa-tls1_2-v-cp4r3-01 p2-2xa-tls1_2-v-cp4r3-01 p2-5xa-tls1_2-v-cp4r3-01 p1-1xa-tls1-v-cp5-01 p2-1xa-tls1-v-cp5-01 p2-2xa-tls1-v-cp5-01 p2-5xa-tls1-v-cp5-01 p1-1xa-tls1_1-v-cp5-01 p2-1xa-tls1_1-v-cp5-01 p2-2xa-tls1_1-v-cp5-01 p2-5xa-tls1_1-v-cp5-01 p1-1xa-tls1_2-v-cp5-01 p2-1xa-tls1_2-v-cp5-01 p2-2xa-tls1_2-v-cp5-01 p2-5xa-tls1_2-v-cp5-01\r
+set SERVER_TESTS=cp20 cp21 csp36r4 csp39 csp4 csp4r3 csp5\r
+set OPENSSL_DEBUG_MEMORY=on\r
+\r
+FOR %%t IN (%BASE_TESTS%) DO %TCLSH% %%t.try\r
+FOR %%t IN (%PKCS7_COMPATIBILITY_TESTS%) DO %TCLSH% %%t.try\r
+rem FOR %%t IN (%SERVER_TESTS%) DO %TCLSH% server.try %%t\r
+rem FOR %%t IN (%CLIENT_TESTS%) DO %TCLSH% client.try %%t\r
+set CVS_RSH=ssh\r
+rem FOR %%t IN (%WINCLIENT_TESTS%) DO %TCLSH% wcli.try %%t\r
+IF EXIST %TESTDIR%\%OTHER_DIR% %TCLSH% interop.try\r
+IF EXIST %TESTDIR%\%OTHER_VERSION% (\r
+       set OTHER_DIR=%OTHER_VERSION%\r
+       IF %ENGINE_NAME%==cryptocom (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       ) ELSE (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       )\r
+       %TCLSH% interop.try\r
+)\r
+\r
+%TCLSH% calcstat %TESTDIR%\stats %TESTDIR%\test.result\r
diff --git a/tcl_tests/runtest2.bat b/tcl_tests/runtest2.bat
new file mode 100755 (executable)
index 0000000..ab7ccaf
--- /dev/null
@@ -0,0 +1,81 @@
+@echo off\r
+\r
+rem Состав набора тестов\r
+rem 1. Этот скрипт\r
+rem 2. Файлы *.try\r
+rem 3. Файлы *.tcl\r
+rem 4. Файлы *.ciphers\r
+rem 5. calcstat\r
+rem 6. oidfile\r
+rem 7. name2oid.tst\r
+\r
+rem Пререквизиты, которые должны быть установлены на машине:\r
+rem 1. tclsh.\r
+rem 2. ssh (что характерно, называться должен именно так и не должен выводить\r
+rem лишних сообщений), мы используем ssh.bat вокруг putty:\r
+rem @plink -l build %*\r
+rem Должен и настроен заход по ключам без пароля на lynx и все используемые\r
+rem эталонники. Ключи этих машин должны быть в knownhosts с полными доменными \r
+rem именами серверов, то есть lynx.lan.cryptocom.ru и т.д. (для putty \r
+rem knownhosts хранятся в реесте).\r
+rem В Firewall Windows необходимо прописать исключение, разрешающее \r
+rem соединения для программы openssl.exe. Внимание, Windows неправильно \r
+rem трактует понятие "локальная сеть" в описании исключения, нужно либо\r
+rem выставлять "любой компьютер", либо явно задавать маску 10.51.0.0/255.255.0.0\r
+\r
+\r
+IF "%OPENSSL_APP%"=="" set OPENSSL_APP=c:\cryptopack3\bin\openssl.exe\r
+IF "%TCLSH%"=="" set TCLSH=c:\Tcl\bin\tclsh.exe\r
+\r
+%TCLSH% getengine.tcl > engine_name.txt\r
+set /p ENGINE_NAME= < engine_name.txt\r
+del engine_name.txt\r
+\r
+hostname > host_name.txt\r
+set /p HOST_NAME= < host_name.txt\r
+del host_name.txt\r
+set TESTDIR=%HOST_NAME%-bat-%ENGINE_NAME%\r
+rem emdir /s /q %TESTDIR%\r
+rem mkdir %TESTDIR%\r
+rem copy oidfile %TESTDIR%\r
+set OTHER_VERSION=../OtherVersion\r
+\r
+IF %ENGINE_NAME%==cryptocom (\r
+               set BASE_TESTS=engine ssl dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-gost\r
+) ELSE (\r
+       IF %ENGINE_NAME%==gost (\r
+               set BASE_TESTS=engine dgst pkcs8 enc req-genpkey req-newkey ca smime smime2 smimeenc cms cms2 cmsenc pkcs12 nopath ocsp ts ssl smime_io cms_io smimeenc_io cmsenc_io\r
+               set OTHER_DIR=../%HOST_NAME%-bat-cryptocom\r
+       ) ELSE (\r
+               echo No GOST providing engine found\r
+               exit 1\r
+       )\r
+)\r
+\r
+set PKCS7_COMPATIBILITY_TESTS=smime_cs cmsenc_cs cmsenc_sc\r
+set CLIENT_TESTS=cp20 cp21\r
+set WINCLIENT_TESTS=p1-1xa-tls1-v-cp36r4-srv p1-1xa-tls1-v-cp39-srv p1-1xa-tls1-v-cp4-01 p2-1xa-tls1-v-cp4-01 p2-2xa-tls1-v-cp4-12S p2-5xa-tls1-v-cp4-12L p1-1xa-tls1-v-cp4r3-01 p2-1xa-tls1-v-cp4r3-01 p2-2xa-tls1-v-cp4r3-01 p2-5xa-tls1-v-cp4r3-01 p1-1xa-tls1_1-v-cp4r3-01 p2-1xa-tls1_1-v-cp4r3-01 p2-2xa-tls1_1-v-cp4r3-01 p2-5xa-tls1_1-v-cp4r3-01 p1-1xa-tls1_2-v-cp4r3-01 p2-1xa-tls1_2-v-cp4r3-01 p2-2xa-tls1_2-v-cp4r3-01 p2-5xa-tls1_2-v-cp4r3-01 p1-1xa-tls1-v-cp5-01 p2-1xa-tls1-v-cp5-01 p2-2xa-tls1-v-cp5-01 p2-5xa-tls1-v-cp5-01 p1-1xa-tls1_1-v-cp5-01 p2-1xa-tls1_1-v-cp5-01 p2-2xa-tls1_1-v-cp5-01 p2-5xa-tls1_1-v-cp5-01 p1-1xa-tls1_2-v-cp5-01 p2-1xa-tls1_2-v-cp5-01 p2-2xa-tls1_2-v-cp5-01 p2-5xa-tls1_2-v-cp5-01\r
+set SERVER_TESTS=cp20 cp21 csp36r4 csp39 csp4 csp4r3 csp5\r
+set OPENSSL_DEBUG_MEMORY=on\r
+\r
+rem eOR %%t IN (%BASE_TESTS%) DO %TCLSH% %%t.try\r
+rem FOR %%t IN (%PKCS7_COMPATIBILITY_TESTS%) DO %TCLSH% %%t.try\r
+FOR %%t IN (%SERVER_TESTS%) DO %TCLSH% server.try %%t\r
+FOR %%t IN (%CLIENT_TESTS%) DO %TCLSH% client.try %%t\r
+set CVS_RSH=ssh\r
+FOR %%t IN (%WINCLIENT_TESTS%) DO %TCLSH% wcli.try %%t\r
+IF EXIST %TESTDIR%\%OTHER_DIR% %TCLSH% interop.try\r
+IF EXIST %TESTDIR%\%OTHER_VERSION% (\r
+       set OTHER_DIR=%OTHER_VERSION%\r
+       IF %ENGINE_NAME%==cryptocom (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       ) ELSE (\r
+               set ALG_LIST="gost2001:A gost2001:B gost2001:C" \r
+               set ENC_LIST="gost2001:A:1.2.643.2.2.31.3 gost2001:B:1.2.643.2.2.31.4 gost2001:C:1.2.643.2.2.31.2 gost2001:A:"\r
+       )\r
+       %TCLSH% interop.try\r
+)\r
+\r
+%TCLSH% calcstat %TESTDIR%\stats %TESTDIR%\test.result\r
diff --git a/tcl_tests/server.try b/tcl_tests/server.try
new file mode 100644 (file)
index 0000000..bc12638
--- /dev/null
@@ -0,0 +1,205 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+
+
+package require ossltest
+
+if {$argc != 1} {
+       puts stderr "Usage $argv0 cipher-list-file"
+       exit 1
+}      
+array set protos {
+       SSLv2 -ssl2
+       SSLv3 -ssl3
+       TLSv1 -tls1
+       TLSv1.1 -tls1_1
+       TLSv1.2 -tls1_2
+       "default" {}
+}
+get_hosts [lindex $argv 0]
+cd $::test::dir
+start_tests "TLS-соединение с сервером [lindex $argv 0]"
+
+if {[engine_name] eq "ccore"} {
+       array unset hosts gost94*
+}
+
+array set suite_map {
+CRYPTOPRO-DHGOST94-DSS-GOST89-STREAMGOST89 GOST94-GOST89-GOST89
+CRYPTOPRO-DHGOST94-DSS-NULL-GOST94 GOST94-NULL-GOST94
+CRYPTOPRO-DHGOST-DSS-GOST89-STREAMGOST89 GOST2001-GOST89-GOST89
+CRYPTOPRO-DHGOST-DSS-NULL-GOST94 GOST2001-NULL-GOST94
+}
+
+set CAhost lynx.lan.cryptocom.ru  
+set CAprefix /cgi-bin/autoca 
+
+foreach alg [array names hosts] {
+       set alg2 [regsub {(gost\d+)cp} $alg {\1}]
+       set alg_fn [string map {":" "_"} $alg2]
+       set alg_short [regexp -inline {^[^:]+} $alg2]
+       set alg_ca [regexp -inline {^[^:]+} $alg]
+
+       test -skip {[file exist ca_$alg_short.pem]} "Получить сертификат $alg_ca CA" {
+               getCAcert $CAhost $CAprefix $alg_ca
+       } 0 "ca_$alg_ca.pem"
+
+       if {[array exists suites]} {array unset suites}
+       array set suites $hosts($alg)
+       foreach suite [array names suites] {
+               if {![regexp {(.+):(.+)} $suite => proto cs]} {
+                       set cs $suite
+                       set proto "default"
+               }
+               if {[info exists suite_map($cs)]} {
+                       set mycs $suite_map($cs)
+               } else {
+                       set mycs $cs
+               }       
+               if {![regexp {(.+:\d+):(.*)} $suites($suite) x url servertype]} {
+                       set servertype apache
+                       set url $suites($suite)
+               }       
+               if {$servertype eq "iis"} {
+                       set failure "HTTP 403.7 - Forbidden: Client certificate required"
+                       set failure_exit_code 0
+               } else {
+                       set failure "ssl handshake failure"
+                       set failure_exit_code 1
+               }
+               
+               regexp {(.+):(\d+)} $url dummy get_hostname get_port
+
+               test "$suite статическая страница " {        
+                       grep "<H1>" [openssl [concat s_client $protos($proto) \
+                               [list -cipher $mycs -CAfile ca_$alg_ca.pem -connect $url \
+                               -verify_return_error -verify 1 -ign_eof \
+                               << "GET /ssl_test.html HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+               } 0 "<H1>Test SSL static page</H1>\n"
+
+
+               test "$suite большая страница" {
+                       grep "<H1>" [openssl [concat s_client $protos($proto) \
+                               [list -cipher $mycs -CAfile ca_$alg_ca.pem -connect $url \
+                               -verify_return_error -verify 1 -ign_eof \
+                               << "GET /ssl_test_big.html HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+               } 0 "<H1>Big test SSL static page</H1>\n"       
+
+
+               if {$servertype eq "iis"} {
+                       test "$suite скрипт printenv.asp" {
+                               grep "SERVER_PORT_SECURE:" [openssl \
+                                       [concat s_client $protos($proto) \
+                                       [list -cipher $mycs -CAfile ca_$alg_ca.pem\
+                                       -connect $url -verify_return_error -verify 1 -ign_eof \
+                                       << "GET /printenv.asp HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                       } 0 "SERVER_PORT_SECURE: 1\n"
+               } else {
+                       test "$suite скрипт printenv" {
+                               grep "SSL_CIPHER=" [openssl \
+                                       [concat s_client $protos($proto) \
+                                       [list -cipher $mycs -CAfile ca_$alg_ca.pem \
+                                       -connect $url -verify_return_error -verify 1 -ign_eof \
+                                       << "GET /cgi-bin/printenv HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                       } 0 "SSL_CIPHER=\"$cs\"\n"
+               }
+
+               if {[string match *GOST2012* $suite]} {
+                       set alg_cli_list "$alg gost2001:B gost2012_256:B gost2012_512:B"
+               } elseif {[string match *GOST2001* $suite]} {
+                       set alg_cli_list "$alg gost2001:B"
+               } else {
+                       set alg_cli_list $alg
+               }
+
+               foreach alg_cli $alg_cli_list {
+                       set alg_cli_fn [string map {":" "_"} $alg_cli]
+                       set alg_cli_short [regexp -inline {^[^:]+} $alg_cli]
+
+                       test -skip {[file exist U_x_$alg_cli_fn/cert.pem]} "Получение клиентского сертификата $alg_cli" {
+                               getCAAlgParams  $CAhost $CAprefix $alg_cli_short
+                               if {![makeUser U_x_$alg_cli_fn $alg_cli CN \
+                               "Test engine on [info hostname]"]} {
+                                       error "Request generation failed"
+                               }
+                               registerUserAtCA U_x_$alg_cli_fn $CAhost $CAprefix $alg_ca
+                               file exists U_x_$alg_cli_fn/cert.pem
+                       } 0 1
+
+
+                       test "$suite  нет сертификата, статичеcкая страница" {
+                               set out [openssl [concat s_client $protos($proto) \
+                                       [list -msg -cipher $mycs -CAfile ca_$alg_ca.pem \
+                                       -verify_return_error -verify 1 -connect $url -ign_eof \
+                                       << "GET /ssl_auth_test.html HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                               if {[regexp $failure $out match]} {
+                                       set match
+                               } else {
+                                       set out
+                               }       
+                       } $failure_exit_code $failure
+
+
+                       test -skip {![file exists U_x_$alg_cli_fn/cert.pem]} \
+                       "$suite, есть сертификат, статическая страница" {
+                               grep "<H1>" [openssl [concat s_client $protos($proto) \
+                                       [list -msg -cipher $mycs -cert U_x_$alg_cli_fn/cert.pem \
+                                       -key U_x_$alg_cli_fn/seckey.pem -CAfile ca_$alg_ca.pem \
+                                       -verify_return_error -verify 1 -connect $url -ign_eof \
+                                       << "GET /ssl_auth_test.html HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                       } 0 "<H1>Test SSL static page</H1>\n"
+
+
+                       if {$servertype eq "iis"} {
+
+                               test "$suite, нет сертификата, скрипт printenv_auth.asp" {
+                                       set out [openssl [concat s_client $protos($proto) \
+                                               [list -msg -cipher $mycs -CAfile ca_$alg_ca.pem \
+                                               -verify_return_error -verify 1 -connect $url -ign_eof \
+                                               << "GET /printenv_auth.asp HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                                       if {[regexp $failure $out match]} {
+                                               set match
+                                       } else {
+                                               set out
+                                       }       
+                               } 0 $failure 
+
+
+                               test  -skip {![file exists U_x_$alg_cli_fn/cert.pem]} \
+                               "$suite, есть сертификат, скрипт printenv_auth.asp" {
+                                       grep CERT_FLAGS [openssl [concat s_client $protos($proto) \
+                                               [list -msg -cipher $mycs -cert U_x_$alg_cli_fn/cert.pem\
+                                               -key U_x_$alg_cli_fn/seckey.pem -CAfile ca_$alg_ca.pem \
+                                               -verify_return_error -verify 1 -connect $url -ign_eof \
+                                               << "GET /printenv_auth.asp HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                               } 0 "CERT_FLAGS: 1\n"   
+
+                       } else {
+
+                               test "$suite, нет сертификата, скрипт printenv" {
+                                       set out [openssl [concat s_client $protos($proto) \
+                                               [list -cipher $mycs -CAfile ca_$alg_ca.pem \
+                                               -verify_return_error -verify 1 -connect $url -ign_eof \
+                                               << "GET /cgi-bin/printenv/auth HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                                       if {[regexp "ssl handshake failure" $out match]} {
+                                               set match
+                                       } else {
+                                               set out
+                                       }       
+                               } 1 "ssl handshake failure" 
+
+                               test  -skip {![file exists U_x_$alg_cli_fn/cert.pem]} \
+                               "$suite, есть сертификат, скрипт printenv" {
+                                       grep SSL_CLIENT_VERIFY [openssl \
+                                               [concat s_client $protos($proto) \
+                                               [list -cipher $mycs -cert U_x_$alg_cli_fn/cert.pem \
+                                               -key U_x_$alg_cli_fn/seckey.pem -CAfile ca_$alg_ca.pem \
+                                               -verify_return_error -verify 1 -connect $url -ign_eof \
+                                               << "GET /cgi-bin/printenv/auth HTTP/1.1\nHost: $get_hostname\nConnection: close\n\n"]]]
+                               } 0 "SSL_CLIENT_VERIFY=\"SUCCESS\"\n"   
+                       }
+               }       
+       }       
+}      
+end_tests
diff --git a/tcl_tests/smime.try b/tcl_tests/smime.try
new file mode 100644 (file)
index 0000000..cd610ba
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на команду smime" 
+
+test "Creating CA 2001" {
+       makeCA ${testname}CA gost2001:A
+} 0 1
+
+test "Creating CA 2012" {
+       makeCA
+} 0 1
+
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_smime_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca ${testname}CA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca ${testname}CA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+
+test "Creating user with signing 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
+
+test -skip {![file exists $username/cert.pem]} -createsfiles [list sign.dat sign_$alg_fn.msg] "Signing a message without cert by $alg" {
+       makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+       openssl "smime -sign -in sign.dat -text -out sign_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nocerts"
+       file isfile sign_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist sign_$alg_fn.msg]} "Checking micalg param in signed without cert $alg message" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile sign_$alg_fn.msg]]
+} 0 1
+
+test -createsfiles sign_$alg_fn.pem -skip {![file exist sign_$alg_fn.msg]} "Extracting PKCS7 from signed without cert $alg message" {
+       openssl "smime -pk7out -out sign_$alg_fn.pem -in sign_$alg_fn.msg"
+       file isfile sign_$alg_fn.pem
+} 0 1
+
+
+test -skip {![file exists sign_$alg_fn.pem]} "Checking oids in pkcs7 struct" {
+       extract_oids sign_$alg_fn.pem PEM
+} 0 [mkObjList [hash_long_name $alg] [hash_long_name $alg] "GOST R 34.11-2012 with 256 bit hash" "GOST R 34.11-2012 with 512 bit hash" "GOST R 34.11-94" "GOST 28147-89" [alg_long_name $alg]] 
+#[mkObjList [alg_hash $alg] [alg_hash $alg] hash_12_256 hash_12_512 hash_94 crypt89_cc [alg_id $alg]] 
+# hash_12_256 hash_12_512 hash_94 crypt89_cc are from sMIMECapabilities
+
+test -skip {![file exists sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca " {
+       grep Veri [openssl "smime -verify -text -in sign_$alg_fn.msg -out verified.txt -noverify -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca" {
+       grep Veri [openssl "smime -verify -text -in sign_$alg_fn.msg -out verified.txt -certfile $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]} -createsfiles [list bad_$alg_fn.msg verified.txt] "Verifying corrupted messages signed with $alg" {
+       set corrupted [getFile sign_$alg_fn.msg]
+       set index [string first "Test data" $corrupted ]
+       makeFile bad_$alg_fn.msg [string replace $corrupted $index [expr $index+9] "Bad data"]
+       grep Verification [openssl "smime -verify -text -in bad_$alg_fn.msg -out verified.txt -noverify -certfile $username/cert.pem"]
+} 1 "Verification failure"
+
+test -skip {![file exists $username/cert.pem]}  -createsfiles [list sign.dat sign_c_$alg_fn.msg] "Signing a message by $alg with cert" {
+       makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+       openssl "smime -sign -in sign.dat -crlfeol -text -out sign_c_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+       file isfile sign_c_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist sign_c_$alg_fn.msg]} "Checking micalg param in signed with cert $alg message" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile sign_c_$alg_fn.msg]]
+} 0 1
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca" {
+       grep Veri [openssl "smime -verify -text -in sign_c_$alg_fn.msg -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca" {
+       grep Veri [openssl "smime -verify -text -in sign_c_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+test -skip {![file exists $username/cert.pem]} -createsfiles {sign.dat sign_op_$alg_fn.msg} "Signing a message by $alg with cert using opaque signing" {
+       makeFile sign.dat [string repeat "Test data to sign.\n" 100] 
+       openssl "smime -sign -in sign.dat -text -out sign_op_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem -nodetach"
+       file isfile sign_op_$alg_fn.msg
+} 0 1
+
+test -createsfiles verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca" {
+       grep Veri [openssl "smime -verify -text -in sign_op_$alg_fn.msg -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -createsfiles verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca" {
+       grep Veri [openssl "smime -verify -text -in sign_op_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -createsfiles broken_op_$alg_fn.msg  -skip {![file exists sign_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       set data [getFile sign_op_$alg_fn.msg]
+       regexp "(.*)\n\r?\n(.+)" $data match header encoded
+       set asnstruct [::base64::decode $encoded]
+       makeFile broken_op_$alg_fn.msg "$header\n\n[::base64::encode [regsub -all\
+               "Test data" $asnstruct "Best data"]]"
+       grep Verification [openssl "smime -verify -text -in broken_op_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+       
+
+test -createsfiles "sign_det_$alg_fn.msg" -skip {![file exists $username/cert.pem]||![file exists sign.dat]} "Creating detached $alg signature" {
+       openssl "smime -sign -binary -in sign.dat -out sign_det_$alg_fn.msg -signer $username/cert.pem -inkey $username/seckey.pem"
+       file exists sign_det_$alg_fn.msg
+} 0 1
+
+test -skip {![file exist sign_det_$alg_fn.msg]} "Checking micalg param in detached $alg signature" {
+       regexp -- micalg="[micalg [alg_hash $alg]]" [grep micalg [getFile sign_det_$alg_fn.msg]]
+} 0 1
+
+test -createsfiles sign_det_$alg_fn.pem -skip {![file exist sign_det_$alg_fn.msg]} "Extracting PKCS7 from signed $alg message" {
+       openssl "smime -pk7out -out sign_det_$alg_fn.pem -in sign_det_$alg_fn.msg"
+       file isfile sign_det_$alg_fn.pem
+} 0 1
+
+#We expect cryptocom oids because of cert signed by ca with Cryptocom algs
+# Result sequence
+# 1. digest 
+# 2.  algorithm of CA key
+# 3. algorithm of current key
+# 4. algorithm of CA key
+# 5. digest
+# 6. digests from sMIMECapabilities
+# 7. encryption from sMIMECapabilities
+# 8. algorithm of current key
+test -skip {![file exists sign_det_$alg_fn.pem]} "Checking oids in pkcs7 struct" {
+       extract_oids sign_det_$alg_fn.pem PEM
+} 0 [mkObjList [hash_long_name $alg] [smime_hash_with_sign_long_name $ca_sign_alg] [alg_long_name $alg] [pubkey_long_name $alg] [param_hash_long_name [param_hash $alg]] [smime_hash_with_sign_long_name  $ca_sign_alg] [hash_long_name $alg] "GOST R 34.11-2012 with 256 bit hash" "GOST R 34.11-2012 with 512 bit hash" "GOST R 34.11-94" "GOST 28147-89" [alg_long_name $alg]]
+
+test -skip {![file exists sign_det_$alg_fn.pem]} "Verifying detached $alg signature" {
+       grep Veri [openssl "smime -verify -content sign.dat -inform PEM -in sign_det_$alg_fn.pem -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_det_$alg_fn.msg]} -createsfiles {bad.dat} "Verifying corrupted $alg detached signature" {
+       makeFile bad.dat [regsub Test [getFile sign.dat] Best]
+       grep Verification [openssl "smime -verify -content bad.dat -in sign_det_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+
+
+}
+end_tests
diff --git a/tcl_tests/smime2.try b/tcl_tests/smime2.try
new file mode 100644 (file)
index 0000000..c3bdd12
--- /dev/null
@@ -0,0 +1,205 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду smime - вторая подпись" 
+
+test "Creating CA" {
+       makeCA
+} 0 1
+
+makeFile signed2.dat "Test data for 2 signatures"
+
+
+foreach length {256 512} {
+
+test "Creating users $length" {
+       makeRegisteredUser U_smime_1_$length gost2012_$length:A CN USER1_$length emailAddress test@cryptocom.ru
+       makeRegisteredUser U_smime_2_$length gost2012_$length:A CN USER2_$length emailAddress test@cryptocom.ru
+} 0 1
+
+test -createsfiles signed2_1_$length.asn "Signing in DER format with 1st signature" {
+       openssl "smime -sign -binary -outform der -inform der -nodetach -inkey U_smime_1_$length/seckey.pem -signer U_smime_1_$length/cert.pem -in signed2.dat -out signed2_1_$length.asn"
+       file isfile signed2_1_$length.asn
+} 0 1
+
+test -createsfiles signed2_2_$length.asn "Signing in DER format with 2nd signature" {
+       openssl "smime -resign -binary -outform der -inform der -nodetach -inkey U_smime_2_$length/seckey.pem -signer U_smime_2_$length/cert.pem -in signed2_1_$length.asn -out signed2_2_$length.asn"
+       file isfile signed2_2_$length.asn
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying signature" {
+       grep "Verif" [openssl "smime -verify -inform der -in signed2_2_$length.asn -noverify -signer signer.certs -out was_signed.dat"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles signed2_1_$length\_op.msg "Signing opaque in S/MIME format with 1st signature" {
+       openssl "smime -sign -binary -nodetach -inkey U_smime_1_$length/seckey.pem -signer U_smime_1_$length/cert.pem -in signed2.dat -out signed2_1_$length\_op.msg"
+       file isfile signed2_1_$length\_op.msg
+} 0 1
+
+test -createsfiles signed2_2_$length\_op.msg "Signing opaque in S/MIME format with 2nd signature" {
+       openssl "smime -resign -binary -nodetach -inkey U_smime_2_$length/seckey.pem -signer U_smime_2_$length/cert.pem -in signed2_1_$length\_op.msg -out signed2_2_$length\_op.msg"
+       file isfile signed2_2_$length\_op.msg
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying opaque signature" {
+       grep "Verif" [openssl "smime -verify -inform smime -in signed2_2_$length\_op.msg -noverify -signer signer.certs -out was_signed.dat"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles signed2_1_$length\_det.asn "Signing detached in DER format with 1st signature" {
+       openssl "smime -sign -binary -outform der -inkey U_smime_1_$length/seckey.pem -signer U_smime_1_$length/cert.pem -in signed2.dat -out signed2_1_$length\_det.asn"
+       file isfile signed2_1_$length\_det.asn
+} 0 1
+
+test -createsfiles signed2_2_$length\_det.asn "Signing detached in DER format with 2nd signature" {
+       openssl "smime -resign -binary -inkey U_smime_2_$length/seckey.pem -signer U_smime_2_$length/cert.pem -in signed2_1_$length\_det.asn -content signed2.dat -inform der -outform der -out signed2_2_$length\_det.asn"
+       file isfile signed2_2_$length\_det.asn
+} 0 1
+
+test -createsfiles {was_signed.dat signer.certs} "Verifying detached signature in DER format" {
+       grep "Verif" [openssl "smime -verify -in signed2_2_$length\_det.asn -noverify -signer signer.certs -out was_signed.dat -content signed2.dat -inform der"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert_asn[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert_asn$i.pem -subject -noout"]]
+       }
+       lsort  $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+test -createsfiles signed2_1_$length.msg "Signing in S/MIME format with 1st signature" {
+       openssl "smime -sign -binary -inform der -inkey U_smime_1_$length/seckey.pem -signer U_smime_1_$length/cert.pem -in signed2.dat -out signed2_1_$length.msg"
+       file isfile signed2_1_$length.msg
+} 0 1
+
+test -createsfiles signed2_2_$length.msg "Signing in S/MIME format with 2nd signature" {
+       grep "SMIME" [openssl "smime -resign -binary -inkey U_smime_2_$length/seckey.pem -signer U_smime_2_$length/cert.pem -in signed2_1_$length.msg -inform smime -out signed2_2_$length.msg"]
+} 0 ""
+
+test -createsfiles {was_signed.dat  signer.certs} "Verifying signature" {
+       grep "Verif" [openssl "smime -verify -in signed2_2_$length.msg -noverify -signer signer.certs -out was_signed.dat -inform smime"]
+} 0 {Verification successful
+}
+
+test "Signed data is extracted correctly" {
+       string eq [getFile signed2.dat] [getFile was_signed.dat]
+} 0 1
+
+### Test extracted sertificates
+
+test "Extracting signer certificates" {
+       set i 0
+       set subjs {}
+       set certs [regexp -all -inline -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} [getFile signer.certs]]
+       foreach cert $certs {
+               makeFile cert_smime[incr i].pem $cert
+               lappend subjs [grep subject [openssl "x509 -in cert_smime$i.pem -subject -noout"]]
+       }
+       lsort $subjs
+} 0  "{subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER1_$length, emailAddress = test@cryptocom.ru
+} {subject=C = RU, O = Cryptocom, OU = OpenSSL Team, CN = USER2_$length, emailAddress = test@cryptocom.ru
+}"
+
+}
+
+
+test "Resigning in DER format with a unsuitable key length 512" {
+       openssl "smime -resign -binary -inform der -nodetach -inkey U_smime_2_512/seckey.pem -signer U_smime_2_512/cert.pem -in signed2_1_256.asn"
+} 1 "no matching digest"
+
+test "Resigning in DER format with a unsuitable key length 256" {
+       openssl "smime -resign -binary -inform der -nodetach -inkey U_smime_2_256/seckey.pem -signer U_smime_2_256/cert.pem -in signed2_1_512.asn"
+} 1 "no matching digest"
+
+test "Resigning opaque in S/MIME format with a unsuitable key length 512" {
+       openssl "smime -resign -binary -nodetach -inkey U_smime_2_512/seckey.pem -signer U_smime_2_512/cert.pem -in signed2_1_256_op.msg"
+} 1 "no matching digest"
+
+test "Resigning opaque in S/MIME format with a unsuitable key length 256" {
+       openssl "smime -resign -binary -nodetach -inkey U_smime_2_256/seckey.pem -signer U_smime_2_256/cert.pem -in signed2_1_512_op.msg"
+} 1 "no matching digest"
+
+test "Resigning detached in DER format with a unsuitable key length 512" {
+       openssl "smime -resign -binary -inform der -inkey U_smime_2_512/seckey.pem -signer U_smime_2_512/cert.pem -in signed2_1_256_det.asn -content signed2.dat"
+} 1 "no matching digest"
+
+test "Resigning detached in DER format with a unsuitable key length 256" {
+       openssl "smime -resign -binary -inform der -inkey U_smime_2_256/seckey.pem -signer U_smime_2_256/cert.pem -in signed2_1_512_det.asn -content signed2.dat"
+} 1 "no matching digest"
+
+test "Resigning in S/MIME format with a unsuitable key length 512" {
+       openssl "smime -resign -binary -inkey U_smime_2_512/seckey.pem -signer U_smime_2_512/cert.pem -in signed2_1_256.msg"
+} 1 "no matching digest"
+
+test "Resigning in S/MIME format with a unsuitable key length 256" {
+       openssl "smime -resign -binary -inkey U_smime_2_256/seckey.pem -signer U_smime_2_256/cert.pem -in signed2_1_512.msg"
+} 1 "no matching digest"
+
+
+end_tests
+
+#./load_engine smime -sign -binary -outform der -inform der -nodetach -inkey certs/fstek.key -signer certs/fstek.crt -out signed2 -in signed1
+#./load_engine smime -verify -inform der -in signed2 -noverify
+#./load_engine smime -verify -inform der -in signed2 -noverify -signer sss
+#cat sss
+#history 
+#vim sss
+#./load_engine x509 -in sss sss2
+#./load_engine x509 -in sss 
+#./load_engine x509 -in sss -subject -noout
+#./load_engine x509 -in sss2 -subject -noout
+#./load_engine smime -verify -inform der -in signed2 -noverify -signer sss -out qqq
diff --git a/tcl_tests/smime_cs.try b/tcl_tests/smime_cs.try
new file mode 100644 (file)
index 0000000..1a01451
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на восместимость по подписи с эталонными серверами" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_smime_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca smimeCA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca smimeCA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+set hosts [list tls-ref-cp21]
+foreach hstname $hosts {
+
+
+test -skip {![file exists sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca via cms" {
+       grep Veri [openssl_remote "$username sign_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_$alg_fn.msg -out TESTPATH/verified.txt -noverify -certfile TESTPATH/$username/cert.pem" "smime"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca via cms" {
+       grep Veri [openssl_remote "$::test::ca sign_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_$alg_fn.msg -out TESTPATH/verified.txt -certfile TESTPATH/$username/cert.pem -CAfile TESTPATH/$::test::ca/cacert.pem" "smime"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists bad_$alg_fn.msg]} -createsfiles TESTPATH/verified.txt] "Verifying corrupted messages signed with $alg via cms" {
+       grep Verification [openssl_remote "bad_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/bad_$alg_fn.msg -out TESTPATH/verified.txt -noverify -certfile TESTPATH/$username/cert.pem" "smime"]
+} 1 "Verification failure"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca via cms" {
+       grep Veri [openssl_remote "sign_c_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_c_$alg_fn.msg -out TESTPATH/verified.txt -noverify" "smime"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca via cms" {
+       grep Veri [openssl_remote "sign_c_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_c_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "smime"]
+} 0 "Verification successful
+"
+
+test -createsfiles TESTPATH/verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca via cms" {
+       grep Veri [openssl_remote "sign_op_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_op_$alg_fn.msg -out TESTPATH/verified.txt -noverify" "smime"]
+} 0 "Verification successful
+"
+
+test -createsfiles TESTPATH/verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca via cms" {
+       grep Veri [openssl_remote "sign_op_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/sign_op_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "smime"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists broken_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       grep Verification [openssl_remote "broken_op_$alg_fn.msg" "$hstname" "cms -verify -text -in TESTPATH/broken_op_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "smime"]
+} 1 "Verification failure"
+
+test -skip {![file exists sign_det_$alg_fn.pem]} "Verifying detached $alg signature via cms" {
+       grep Veri [openssl_remote "sign_det_$alg_fn.pem sign.dat" "$hstname" "cms -verify -content TESTPATH/sign.dat -inform PEM -in TESTPATH/sign_det_$alg_fn.pem -out TESTPATH/verified.txt -noverify" "smime"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_det_$alg_fn.msg] || ![file exists bad.dat]} "Verifying corrupted $alg detached signature" {
+       grep Verification [openssl_remote "sign_det_$alg_fn.msg bad.dat" "$hstname" "cms -verify -content TESTPATH/bad.dat -in TESTPATH/sign_det_$alg_fn.msg -out TESTPATH/verified.txt -CAfile TESTPATH/$::test::ca/cacert.pem" "smime"]
+} 1 "Verification failure"
+}
+
+}
+end_tests
diff --git a/tcl_tests/smime_io.try b/tcl_tests/smime_io.try
new file mode 100644 (file)
index 0000000..ec4df2d
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на совместимость smime и cms -sign" 
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+               "open" {set alg_list {gost2001:A gost2001:B gost2001:C gost2012_256:A gost2012_256:B gost2012_256:C gost2012_512:A gost2012_512:B}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_smime_$alg_fn
+       switch -glob $alg {
+               gost2012* {set ::test::ca smimeCA-2012
+                          set ca_sign_alg hash_with_sign12_512
+                         }
+               * {set ::test::ca smimeCA
+                  set ca_sign_alg hash_with_sign01_cp
+                 }
+       }
+
+test -skip {![file exists sign_$alg_fn.msg]} "Verifying a message signed with $alg without ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_$alg_fn.msg -out verified.txt -noverify -certfile $username/cert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_$alg_fn.msg]}  "Verifying a message signed with $alg with ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_$alg_fn.msg -out verified.txt -certfile $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists bad_$alg_fn.msg]} -createsfiles verified.txt "Verifying corrupted messages signed with $alg via smime" {
+       grep Verification [openssl "cms -verify -text -in bad_$alg_fn.msg -out verified.txt -noverify -certfile $username/cert.pem"]
+} 1 "Verification failure"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert inside without ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_c_$alg_fn.msg -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_c_$alg_fn.msg]} "Verifying a message signed with $alg having cert with ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_c_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -createsfiles verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a message signed by $alg having cert inside without ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_op_$alg_fn.msg -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -createsfiles verified.txt -skip {![file exists sign_op_$alg_fn.msg]} "Verifying a $alg opaque  message with ca via cms" {
+       grep Veri [openssl "cms -verify -text -in sign_op_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists broken_op_$alg_fn.msg]} "Verifying broken $alg opaque message" {
+       grep Verification [openssl "cms -verify -text -in broken_op_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+
+test -skip {![file exists sign_det_$alg_fn.pem]} "Verifying detached $alg signature via cms" {
+       grep Veri [openssl "cms -verify -content sign.dat -inform PEM -in sign_det_$alg_fn.pem -out verified.txt -noverify"]
+} 0 "Verification successful
+"
+
+test -skip {![file exists sign_det_$alg_fn.msg]} -createsfiles {bad.dat} "Verifying corrupted $alg detached signature" {
+       makeFile bad.dat [regsub Test [getFile sign.dat] Best]
+       grep Verification [openssl "cms -verify -content bad.dat -in sign_det_$alg_fn.msg -out verified.txt -CAfile $::test::ca/cacert.pem"]
+} 1 "Verification failure"
+
+}
+end_tests
diff --git a/tcl_tests/smimeenc.try b/tcl_tests/smimeenc.try
new file mode 100644 (file)
index 0000000..ea8be82
--- /dev/null
@@ -0,0 +1,185 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+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 -des -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 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:}}
+       }
+}
+
+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
diff --git a/tcl_tests/smimeenc_io.try b/tcl_tests/smimeenc_io.try
new file mode 100644 (file)
index 0000000..fa991ce
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set testname [file rootname [file tail $::argv0]]
+
+start_tests "Тесты на совместимость smime и cms -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 {![info exist env(NO_RSA)]} {
+
+test -createsfiles io_decrypt.rsa "RSA User 2 (with cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in enc_rsa.msg -recip U_enc_rsa_2/cert.pem -inkey U_enc_rsa_2/seckey.pem -out io_decrypt.rsa"
+       set result [getFile io_decrypt.rsa]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_decrypt_nocert.rsa "RSA User 2 (without cert) can decrypt message for RSA user 2" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in enc_rsa.msg -inkey U_enc_rsa_2/seckey.pem -out io_decrypt_nocert.rsa"
+       set result [getFile io_decrypt_nocert.rsa]
+       string eq $expected $result
+} 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 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:}}
+       }
+}
+
+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 -createsfiles io_decrypt.$alg_fn "Decrypting file encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in enc_$alg_fn.msg -recip U_enc_$alg_fn/cert.pem -inkey U_enc_$alg_fn/seckey.pem -out io_decrypt.$alg_fn"
+       set result [getFile io_decrypt.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_decrypt_t.$alg_fn "Decrypting file text-encrypted for $username" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -text -in enc_t_$alg_fn.msg -recip U_enc_$alg_fn/cert.pem -inkey U_enc_$alg_fn/seckey.pem -out io_decrypt_t.$alg_fn"
+       set result [getFile io_decrypt_t.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -createsfiles io_decrypt_t_nocert.$alg_fn "Decrypting file text-encrypted for $username without cert" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -text -in enc_t_$alg_fn.msg -inkey U_enc_$alg_fn/seckey.pem -out io_decrypt_t_nocert.$alg_fn"
+       set result [getFile io_decrypt_t_nocert.$alg_fn]
+       string eq $expected $result
+} 0 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
+       
+test -skip {![file exists enc_4all.msg]} -createsfiles io_decrypt_4all.$alg_fn "Decrypting gost-encrypted file, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in enc_4all.msg -recip $username/cert.pem -inkey $username/seckey.pem -out io_decrypt_4all.$alg_fn"
+       set result [getFile io_decrypt_4all.$alg_fn]
+       string eq $expected $result
+} 0 1
+
+test -skip {![file exists enc_4all.msg]} -createsfiles io_decrypt_4all_nocert.$alg_fn "Decrypting gost-encrypted file without cert, recipient $alg_fn" {
+       set expected [getFile encrypt.dat]
+       openssl "cms -decrypt -in enc_4all.msg -inkey $username/seckey.pem -out io_decrypt_4all_nocert.$alg_fn"
+       set result [getFile io_decrypt_4all_nocert.$alg_fn]
+       string eq $expected $result
+} 0 1
+}
+
+end_tests
diff --git a/tcl_tests/ssl.try b/tcl_tests/ssl.try
new file mode 100644 (file)
index 0000000..54672bc
--- /dev/null
@@ -0,0 +1,322 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+if {$argc==2} {
+       switch -exact -- [lindex $argv 0]  {
+       -serverconf {
+               set test::server_conf [lindex $argv 1]
+               set test::suffix "-clt"
+       } 
+       -clientconf {
+               set test::client_conf [lindex $argv 1]
+               set test::suffix "-srv"
+       }
+       default {
+               puts stderr "invalid command line"
+               exit 1;
+       }
+       }
+} elseif $argc {
+       puts stderr "invalid command line"
+       exit 1
+}      
+
+array set protos {
+       TLSv1 -tls1
+       TLSv1.1 -tls1_1
+       TLSv1.2 -tls1_2
+}
+
+cd $::test::dir
+
+start_tests "Тесты на SSL-соединение между s_client и s_server"
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {rsa:1024 gost2001:XA gost2012_256:XA gost2012_512:A}}
+               "open" {set alg_list {rsa:1024 gost2001:XA gost2012_256:XA gost2012_512:A}}
+       }
+}
+
+array set suites {
+rsa:1024 {ECDHE-RSA-AES256-SHA}
+gost2001:XA {GOST2001-GOST89-GOST89 GOST2001-NULL-GOST94@SECLEVEL=0 GOST2012-GOST8912-GOST8912 GOST2012-NULL-GOST12@SECLEVEL=0}
+gost2012_256:XA {GOST2012-GOST8912-GOST8912 GOST2012-NULL-GOST12@SECLEVEL=0 GOST2012-MAGMA-MAGMAOMAC GOST2012-KUZNYECHIK-KUZNYECHIKOMAC}
+gost2012_512:A {GOST2012-GOST8912-GOST8912 GOST2012-NULL-GOST12@SECLEVEL=0 GOST2012-MAGMA-MAGMAOMAC GOST2012-KUZNYECHIK-KUZNYECHIKOMAC}
+}
+
+#
+# Incompatible cipher suites
+#
+array set badsuites {
+gost2012_256:XA {GOST2001-GOST89-GOST89 GOST2001-NULL-GOST94@SECLEVEL=0} 
+gost2012_512:A {GOST2001-GOST89-GOST89 GOST2001-NULL-GOST94@SECLEVEL=0}
+}
+
+#
+# Default cipher suite negotiated for algorithm
+#
+array set defsuite {
+rsa:1024 ECDHE-RSA-AES256-SHA
+#gost94:XA GOST94-GOST89-GOST89
+gost2001:XA GOST2012-GOST8912-GOST8912
+gost2012_256:XA GOST2012-GOST8912-GOST8912
+gost2012_512:A GOST2012-GOST8912-GOST8912
+}
+
+array set defsuite_12 {
+rsa:1024 ECDHE-RSA-AES256-GCM-SHA384
+#gost94:XA GOST94-GOST89-GOST89
+gost2001:XA GOST2012-GOST8912-GOST8912
+gost2012_256:XA GOST2012-MAGMA-MAGMAOMAC
+gost2012_512:A GOST2012-MAGMA-MAGMAOMAC
+}
+
+set proto_list {"TLSv1" "TLSv1.1" "TLSv1.2"}
+
+if {![file exists sslCA/cacert.pem]} {
+       makeCA sslCA rsa
+} else {
+       set ::test::ca sslCA    
+}
+
+test -skip {[file exist localhost_rsa/cert.pem]} \
+       "Создаем серверный сертификат rsa" {
+       makeRegisteredUser localhost_rsa rsa:1024 CN localhost
+} 0 1
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       
+       test -skip {[file exist localhost_$alg_fn/cert.pem]} \
+               "Создаем серверный сертификат $alg" {
+               makeRegisteredUser localhost_$alg_fn $alg CN localhost OU $alg_fn
+       } 0 1
+
+       test -skip {[file exists ssl_user_$alg_fn/cert.pem]} \
+               "Создаем клиентский сертификат $alg" {
+               makeRegisteredUser ssl_user_$alg_fn $alg CN ssl_user OU $alg_fn
+       } 0 1
+}
+
+foreach alg {gost2001:B gost2012_256:B gost2012_512:B} {
+       set alg_fn [string map {":" "_"} $alg]
+       test -skip {[file exists ssl_user_$alg_fn/cert.pem]} \
+               "Создаем клиентский сертификат $alg" {
+               makeRegisteredUser ssl_user_$alg_fn $alg CN ssl_user OU $alg_fn
+       } 0 1
+}
+
+
+foreach proto $proto_list {
+       foreach alg $alg_list {
+               set alg_fn [string map {":" "_"} $alg]
+
+               if {[string match *2012* $alg]} {
+                       foreach suite $badsuites($alg) {
+
+                               test "Incompatible suite $alg $suite $proto" {
+                                       set list [client_server [list -connect localhost:4433 \
+                                               -CAfile $::test::ca/cacert.pem \
+                                               -verify_return_error -verify 1 -state -cipher $suite] \
+                                               [list -www -cert localhost_$alg_fn/cert.pem \
+                                               -key localhost_$alg_fn/seckey.pem -cipher $suite \
+                                               $protos($proto)] {}] 
+                                       list [lindex $list 2] [grep "^New," [lindex $list 0]]
+                               } 0 [list 1 "New, (NONE), Cipher is (NONE)\n"]
+                       }
+               }
+
+               foreach suite $suites($alg) {
+                       set raw_name [lindex [split $suite @] 0]
+
+                       if {![string equal $proto "TLSv1.2"] && [string match *OMAC* $suite]} {
+                               continue
+                       }
+
+                       if {[string equal $proto "TLSv1.2"] && [string match *OMAC* $suite]} {
+                               set expected_proto "TLSv1.2"
+                       } else {
+                               set expected_proto "TLSv1.0"
+                       }
+
+                       test "Запуск сервера $suite $proto" {
+                               set f [open_server [list -cert localhost_$alg_fn/cert.pem \
+                                       -key localhost_$alg_fn/seckey.pem -cipher $suite \
+                                       $protos($proto)]]
+                               stop_server $f
+                               foreach {out err status} [stop $f] break        
+                               log "SERVER OUTPUT:\n$out\n----"
+                               log "SERVER STDERR:\n$err\n----"
+                               log "SERVER EXIT CODE: $status"
+                               grep "ACCEPT" $out
+                       } 0 "ACCEPT\n"
+                       log $errorInfo
+                       flush [test_log]
+
+                       test "Корректный хэндшейк $suite $proto" {
+                               set list [client_server [list -connect localhost:4433 \
+                                       -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                       -verify 1 -state -cipher $suite ] \
+                                       [list -www -cert localhost_$alg_fn/cert.pem \
+                                       -key localhost_$alg_fn/seckey.pem \
+                                       -cipher $suite $protos($proto)] {}] 
+                               if {[regexp -lineanchor \
+                               {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                               [lindex $list 0] -> result_proto result_cipher]} {
+                                       list [lindex $list 2] $result_proto $result_cipher
+                               } else {
+                                       lindex $list 1
+                               }       
+                       } 0 [list 0 $proto $raw_name]
+
+
+                       test "Несовпадающий шиферсьют DHE-RSA-AES256-SHA $proto" {
+                               set list [client_server [list -connect localhost:4433 \
+                                       -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                       -verify 1 -state -cipher $suite] \
+                                       [list -www -cert localhost_$alg_fn/cert.pem \
+                                       -key localhost_$alg_fn/seckey.pem \
+                                       -cipher DHE-RSA-AES256-SHA $protos($proto)] {}] 
+                               list [lindex $list 2] [grep ":fatal:" [lindex $list 1]]
+                       } 0 [list 1 "SSL3 alert read:fatal:handshake failure
+"]
+
+                       test "Получение странички $suite $proto" {
+                               set list [client_server [list -connect localhost:4433 \
+                                       -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                       -verify 1 -state -cipher $suite -ign_eof] \
+                                       [list -www -cert localhost_$alg_fn/cert.pem \
+                                       -key localhost_$alg_fn/seckey.pem -cipher $suite \
+                                       $protos($proto)] "GET /\n\n"] 
+                               grep "^New," [lindex $list 0]
+                       } 0 "New, $expected_proto, Cipher is $raw_name\nNew, $expected_proto, Cipher is $raw_name\n"
+
+                       if {![string match "*-NULL-*" $suite]} {
+
+                               test "Сервер поддерживающий много шиферсьютов $proto" {
+                                       set list [client_server [list -connect localhost:4433 \
+                                               -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                               -verify 1 -state -cipher $suite] \
+                                               [list -www -cert localhost_$alg_fn/cert.pem \
+                                               -key localhost_$alg_fn/seckey.pem $protos($proto)] {}] 
+                                       if {[regexp -lineanchor \
+                                       {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                                       [lindex $list 0] -> result_proto result_cipher]} {
+                                               list [lindex $list 2] $result_proto $result_cipher
+                                       } else {
+                                               lindex $list 1
+                                       }       
+                               } 0 [list 0 $proto $suite]
+
+
+                               test "Сервер c несколькими алгоритмами, клиент $suite $proto" {
+                                       set list [client_server [list -connect localhost:4433 \
+                                               -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                               -verify 1 -state -cipher $suite] \
+                                               [list -www -cert localhost_rsa/cert.pem \
+                                               -key localhost_rsa/seckey.pem \
+                                               -dcert localhost_$alg_fn/cert.pem \
+                                               -dkey localhost_$alg_fn/seckey.pem $protos($proto)] {}] 
+                                       if {[regexp -lineanchor \
+                                       {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                                       [lindex $list 0] -> result_proto result_cipher]} {
+                                               list [lindex $list 2] $result_proto $result_cipher
+                                       } else {
+                                               lindex $list 1
+                                       }       
+                               } 0 [list 0 $proto $suite]
+
+                       }
+
+                       test "Сервер c несколькими алгоритмами, клиент AES256-SHA $proto" {
+                               set list [client_server [list -connect localhost:4433 \
+                                       -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                       -verify 1 -state -cipher AES256-SHA] \
+                                       [list -www -cert localhost_rsa/cert.pem \
+                                       -key localhost_rsa/seckey.pem \
+                                       -dcert localhost_$alg_fn/cert.pem \
+                                       -dkey localhost_$alg_fn/seckey.pem $protos($proto)] {}] 
+                               if {[regexp -lineanchor \
+                               {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                               [lindex $list 0] -> result_proto result_cipher]} {
+                                       list [lindex $list 2] $result_proto $result_cipher
+                               } else {
+                                       lindex $list 1
+                               }       
+                       } 0 [list 0 $proto AES256-SHA]
+
+
+
+                       if {[string match *gost* $alg]} {
+                               set alg_cli_list [list $alg gost2001:B gost2012_256:B gost2012_512:B]
+                       } else {
+                               set alg_cli_list $alg
+                       }
+
+                       foreach alg_cli $alg_cli_list { 
+                               set alg_cli_fn [string map {":" "_"} $alg_cli]
+
+                               test "Сервер $alg, клиент с сертификатом $alg_cli $proto" {
+                                       set list [client_server [list -connect localhost:4433\
+                                               -CAfile $::test::ca/cacert.pem -verify_return_error \
+                                               -verify 1 -state -cert ssl_user_$alg_cli_fn/cert.pem \
+                                               -key ssl_user_$alg_cli_fn/seckey.pem -cipher $suite \
+                                               -ign_eof]\
+                                               [list -cert localhost_$alg_fn/cert.pem \
+                                               -key localhost_$alg_fn/seckey.pem -verify_return_error\
+                                               -Verify 3 -www -CAfile $::test::ca/cacert.pem \
+                                               -cipher $suite $protos($proto)] "GET /\n"]
+                                       list [lindex $list 2] [grep "^New," [lindex $list 0]]
+                               } 0 [list 0 [string repeat "New, $expected_proto, Cipher is $raw_name\n" 2]]
+
+                       }
+
+               }
+
+               if {[string equal $proto "TLSv1.2"]} {
+                       set etalon $defsuite_12($alg)
+               } else {
+                       set etalon $defsuite($alg)
+               }
+
+               if {[string equal $proto "TLSv1.2"] && ![string match *2001* $alg]} {
+                       set expected_proto "TLSv1.2"
+               } else {
+                       set expected_proto "TLSv1.0"
+               }
+
+               test "Умолчательный хендшейк с ключами $alg $proto" {
+                       set list [client_server [list -connect localhost:4433\
+                               -CAfile $::test::ca/cacert.pem -verify_return_error -verify 1\
+                               -state -ign_eof]\
+                               [list -www -cert localhost_$alg_fn/cert.pem\
+                               -key localhost_$alg_fn/seckey.pem $protos($proto)] "GET /\n"]
+                       if {[regexp -lineanchor \
+                       {^\s*Protocol\s*:\s*(\S*)\s*$.*^\s*Cipher\s*:\s*(\S*)\s*$} \
+                       [lindex $list 0] -> result_proto result_cipher]} {
+                               list [lindex $list 2] $result_proto $result_cipher
+                       } else {
+                               lindex $list 1
+                       }       
+               } 0 [list 0 $proto $etalon]
+
+               test "Умолчательный хендшейк с клиентской аутентификацией $alg $proto" {
+                       set list [client_server [list -connect localhost:4433\
+                               -CAfile $::test::ca/cacert.pem -verify_return_error \
+                               -verify 1 -state -cert ssl_user_$alg_fn/cert.pem \
+                               -key ssl_user_$alg_fn/seckey.pem -ign_eof]\
+                               [list -cert localhost_$alg_fn/cert.pem \
+                               -key localhost_$alg_fn/seckey.pem -verify_return_error\
+                               -Verify 3 -www -CAfile $::test::ca/cacert.pem $protos($proto)] \
+                               "GET /\n"]
+                       list [lindex $list 2] [grep "^New," [lindex $list 0]]
+               } 0 [list 0 [string repeat "New, $expected_proto, Cipher is $etalon\n" 2]]
+
+       }
+}
+
+end_tests
diff --git a/tcl_tests/tc26_cms/encrypted_keyagree_a211.pem b/tcl_tests/tc26_cms/encrypted_keyagree_a211.pem
new file mode 100644 (file)
index 0000000..9588e62
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CMS-----
+MIIB/gYJKoZIhvcNAQcDoIIB7zCCAesCAQIxggFioYIBXgIBA6CBo6GBoDAXBggq
+hQMHAQEBAjALBgkqhQMHAQIBAgEDgYQABIGAe+itJVNbHM35RHfzuwFJPYdPXqtW
+8hNEF7Z/XFEE2T71SRkhFX7ozYKQNh/TkVY9D4vG0LnD9Znr/pJyOjpsNb+dPcKX
+Kbk/0JQxoPGHxFzASVAFq0ov/yBe2XGFWMeKUqtaAr7SvoYS0oEhT5EuT8BXmecd
+nRe7NqOzESpb15ahIgQgsqHxOcdOp03l11S7k3OH1k1HNa5F8m9ctrOzH2846FMw
+FwYJKoUDBwEBBwIBMAoGCCqFAwcBAQYCMHYwdDBAMDgxDTALBgNVBAoTBFRLMjYx
+JzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdAIEAYy6hQQw
+SxLc18zMwzLwXbcKqYhV/VzsdBgVArOHsSBIbaThJWE7zI37VGPMQJM5VXJ7GVcL
+MF0GCSqGSIb3DQEHATAfBgkqhQMHAQEFAgIwEgQQ6EeVlADDCz2cdEWKy+tM94Av
+yIFl/Ie4VeFFuczTsMsIaOUEe3Jn9GeVp8hZSj3O2q4hslQ/u/+Gj4QkSHm/M0ih
+ITAfBgkqhQMHAQAGAQExEgQQs1t6D3J3WCEvxunnEE15NQ==
+-----END CMS-----
+
diff --git a/tcl_tests/tc26_cms/encrypted_keyagree_a221.pem b/tcl_tests/tc26_cms/encrypted_keyagree_a221.pem
new file mode 100644 (file)
index 0000000..b69ec04
--- /dev/null
@@ -0,0 +1,10 @@
+-----BEGIN CMS-----
+MIIBawYJKoZIhvcNAQcDoIIBXDCCAVgCAQIxgfehgfQCAQOgQjBAMDgxDTALBgNV
+BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp
+dAIEAYy6gqEiBCBvcfyuSF57y8vVyaw8Z0ch3wjC4lPKTrpVRXty4Rhk5DAXBgkq
+hQMHAQEHAQEwCgYIKoUDBwEBBgEwbjBsMEAwODENMAsGA1UEChMEVEsyNjEnMCUG
+A1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0AgQBjLqDBChPbi6B
+krXuLPexPAL2oUGCFWDGQHqINL5ExuMBG7/5XQRqriKARVa0MFkGCSqGSIb3DQEH
+ATAbBgkqhQMHAQEFAQEwDgQMdNdCKnYAAAAwqTEDgC9O2bYyTGQJ8WUQGq0zHwzX
+L0jFhWHTF1tcAxYmd9pX5i89UwIxhtYqyjX1QHju2g==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/encrypted_keytrans_a231.pem b/tcl_tests/tc26_cms/encrypted_keytrans_a231.pem
new file mode 100644 (file)
index 0000000..769457d
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN CMS-----
+MIIBlQYJKoZIhvcNAQcDoIIBhjCCAYICAQAxggEcMIIBGAIBADBAMDgxDTALBgNV
+BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp
+dAIEAYy6gzAXBgkqhQMHAQEHAgEwCgYIKoUDBwEBBgEEgbcwgbQEMFiMredFR3Mv
+3g2wqyVXRnrhYEBMNFaqqgBpHwPQh3bF98tt9HZPxRDCww0OPfxeuTBeMBcGCCqF
+AwcBAQEBMAsGCSqFAwcBAgEBAQNDAARAdFJ9ww+3ptvQiaQpizCldNYhl4DB1rl8
+Fx/2FIgnwssCbYRQ+UuRsTk9dfLLTGJG3JIEXKFxXWBgOrK965A5pAQg9f2/EHxG
+DfetwCe1a6uUDCWD+wp5dYOpfkry8YRDEJgwXQYJKoZIhvcNAQcBMB8GCSqFAwcB
+AQUCATASBBDUHNxmVclO/v3OaY9P7jxOgC+sD9CHGlEMRUpfGn6yfFDMExmYeby8
+LzdPJe1MkYV0qQgdC1zI3nQ7/4taf+4zRA==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/encrypted_keytrans_a241.pem b/tcl_tests/tc26_cms/encrypted_keytrans_a241.pem
new file mode 100644 (file)
index 0000000..f340561
--- /dev/null
@@ -0,0 +1,13 @@
+-----BEGIN CMS-----
+MIIB7wYJKoZIhvcNAQcDoIIB4DCCAdwCAQAxggFfMIIBWwIBADBAMDgxDTALBgNV
+BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp
+dAIEAYy6hTAXBgkqhQMHAQEHAQEwCgYIKoUDBwEBBgIEgfowgfcEMIjuwfzfONBU
+93ktK8OrTr22Q/1IMWaVc2JZxzxoQP5nzT4fq5aUBsY44bEdPhYgRzCBoDAXBggq
+hQMHAQEBAjALBgkqhQMHAQIBAgEDgYQABIGAcaoBV0T9iLYdvUbyw2g6E/mIXerg
+AUAHwAOoXu88GUsTclujKTRgBUDWoRQkEZTPVvPZ58Tx3JWsy2JxJQppwbr9KaoE
+PhnxivZJ2PYG0cK8B/OHiq30I9KwHyGArA3RK4SD2HqoIxeSRWa5IyhoAxSfg5YY
+5LWTXxsNiX+lH9cEIIwDwI/cy7SphgEFu76rkjirn2JHdWiXLTKk4SdG/R+wMFkG
+CSqGSIb3DQEHATAbBgkqhQMHAQEFAQIwDgQM1k2BxkeBXYCEsGMvgC9qSqe1z1h4
+3DHBdQRofT56xVOZCi+JxzUbPqKNzU3vjU2W/LlYgOLGuTJwEzw7GaEZMBcGCSqF
+AwcBAAYBATEKBAgvK0+i46xDsw==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/encrypted_kuznyechik_a421.pem b/tcl_tests/tc26_cms/encrypted_kuznyechik_a421.pem
new file mode 100644 (file)
index 0000000..09aa0fc
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN CMS-----
+MHEGCSqGSIb3DQEHBqBkMGICAQAwXQYJKoZIhvcNAQcBMB8GCSqFAwcBAQUCATAS
+BBBSwX+zyOEPPuGyfpsRG4AigC/P8ftTdQMStfIThVkE/vpJlwaHgGv83m2bsPay
+eyuqpoTeEMOaqGcO0MxHWsC9hQ==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/encrypted_magma_a411.pem b/tcl_tests/tc26_cms/encrypted_magma_a411.pem
new file mode 100644 (file)
index 0000000..15f1e6e
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN CMS-----
+MIGIBgkqhkiG9w0BBwagezB5AgEAMFkGCSqGSIb3DQEHATAbBgkqhQMHAQEFAQIw
+DgQMuncOu3uYPbI30vFCgC9Nsws4R09yLp6jUtadncWUPZGmCGpPKnXGgNHvEmUA
+rgKJvu4FPHtLkHuLeQXZg6EZMBcGCSqFAwcBAAYBATEKBAjCbQoH632oGA==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/encryption_key.hex b/tcl_tests/tc26_cms/encryption_key.hex
new file mode 100644 (file)
index 0000000..76f3bdf
--- /dev/null
@@ -0,0 +1 @@
+8F5EEF8814D228FB2BBC5612323730CFA33DB7263CC2C0A01A6C6953F33D61D5
diff --git a/tcl_tests/tc26_cms/hashed_a311.pem b/tcl_tests/tc26_cms/hashed_a311.pem
new file mode 100644 (file)
index 0000000..8dce781
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN CMS-----
+MH0GCSqGSIb3DQEHBaBwMG4CAQAwCgYIKoUDBwEBAgIwOwYJKoZIhvcNAQcBoC4E
+LMru7fLw7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEuBCD/
+esPQYsGkzxZV8uUMIAWt6SI8KtxBP8NyG8AGbJ8i/Q==
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/hashed_a321.pem b/tcl_tests/tc26_cms/hashed_a321.pem
new file mode 100644 (file)
index 0000000..685a598
--- /dev/null
@@ -0,0 +1,6 @@
+-----BEGIN CMS-----
+MIGfBgkqhkiG9w0BBwWggZEwgY4CAQAwCgYIKoUDBwEBAgMwOwYJKoZIhvcNAQcB
+oC4ELMru7fLw7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEu
+BEDe4VUvcKSRvU7RFVhFjajXY+nJSUkUsoi3oOeJBnru4PErt8RusPrCJs614ciH
+CM+ehrC4a+M1Nbq77F/Wsa/v
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/recipient256_cert.pem b/tcl_tests/tc26_cms/recipient256_cert.pem
new file mode 100644 (file)
index 0000000..43d5486
--- /dev/null
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAZ+gAwIBAgIEAYy6gzAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD
+VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDBoMCEGCCqFAwcB
+AQEBMBUGCSqFAwcBAgEBAQYIKoUDBwEBAgIDQwAEQL8nghlzLGMKWHuWhNMPMN5u
+L6SkGqRiJ6qZxZb+4dPKbBT9LNVvNKtwUed+BeE5kfqOfolPgFusnL1rnO9yREOj
+gYUwgYIwYQYDVR0BBFowWIAUgNkM95n4Zk2TU4mOwJ5xLaenMRKhOjA4MQ0wCwYD
+VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i
+aXSCBAGMuoEwHQYDVR0OBBYEFLue+PUb9Oe+pziBU+MvNejjgrzFMAoGCCqFAwcB
+AQMCA0EAPP9Oad1/5jwokSjPpccsQ0xCdVYM+mGQ0IbpiZxQj8gnkt8sq4jR6Ya+
+I/BDkbZNDNE27TU1p3t5rE9NMEeViA==
+-----END CERTIFICATE-----
diff --git a/tcl_tests/tc26_cms/recipient256_key.pem b/tcl_tests/tc26_cms/recipient256_key.pem
new file mode 100644 (file)
index 0000000..15c291b
--- /dev/null
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQgzre/jOVK
+ur0vHHsZfkIQhvXkUYzK8cOrSxG88h/cyA0=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/tc26_cms/recipient512_cert.pem b/tcl_tests/tc26_cms/recipient512_cert.pem
new file mode 100644 (file)
index 0000000..a26c9c4
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICNTCCAeKgAwIBAgIEAYy6hTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD
+VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgNTEyLWJpdDCBqjAhBggqhQMH
+AQEBAjAVBgkqhQMHAQIBAgEGCCqFAwcBAQIDA4GEAASBgKauwGYvUkzz19g0LP/p
+zeRdmwy1m+QSy9W5ZrL/AGuJofm2ARjz40ozNbW6bp9hkHu8x66LX7u5zz+QeS2+
+X5om18UXriComgO0+qhZbc+Hzu0eQ8FjOd8LpLk3TzzfBltfLOX5IiPLjeum+pSP
+0QjoXAVcrop//B4yvZIukvROo4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJ
+jsCecS2npzESoTowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjog
+R09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBSrXT5VKhm/5uff
+kwW0XpG19k6AajAKBggqhQMHAQEDAgNBAAJBpsHRrQKZGb22LOzaReEB8rl2MbIR
+ja64NaM5h+cAFoHm6t/k+ziLh2A11rTakR+5of4NQ3EjEhuPtomP2tc=
+-----END CERTIFICATE-----
diff --git a/tcl_tests/tc26_cms/recipient512_key.pem b/tcl_tests/tc26_cms/recipient512_key.pem
new file mode 100644 (file)
index 0000000..f7e71c8
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MGgCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRA3HXF+fFK
+6VIJkvHOEhfbcu8ZFQ/bzSS/jLOlrVbAV4fx0YjznHwK387PilH91kv4sWIaWblO
+W8B/fAofmBUDpQ==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/tc26_cms/root256_cert.pem b/tcl_tests/tc26_cms/root256_cert.pem
new file mode 100644 (file)
index 0000000..296fc36
--- /dev/null
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8DCCAZ2gAwIBAgIEAYy6gTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA4MQ0wCwYDVQQKEwRUSzI2MScwJQYD
+VQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMHAQEB
+ATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABEAaSoKcjw54UACci6svELNF0IYM
+RIW8urUsqamIpoG46XCqrVOuI6Q13N4dwcRsbZdqByf+GC2f5ZfO3baN5bTKo4GF
+MIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsGA1UE
+ChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0
+ggQBjLqBMB0GA1UdDgQWBBSA2Qz3mfhmTZNTiY7AnnEtp6cxEjAKBggqhQMHAQED
+AgNBAAgv248F4OeNCkhlzJWec0evHYnMBlSzk1lDm0F875B7CqMrKh2MtJHXenbj
+Gc2uRn2IwgmSf/LZDrYsKKqZSxk=
+-----END CERTIFICATE-----
diff --git a/tcl_tests/tc26_cms/root256_key.pem b/tcl_tests/tc26_cms/root256_key.pem
new file mode 100644 (file)
index 0000000..15c291b
--- /dev/null
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQgzre/jOVK
+ur0vHHsZfkIQhvXkUYzK8cOrSxG88h/cyA0=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/tc26_cms/sender256_cert.pem b/tcl_tests/tc26_cms/sender256_cert.pem
new file mode 100644 (file)
index 0000000..a4694ae
--- /dev/null
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAaCgAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD
+VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMH
+AQEBATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABECWKQ0TYllqg4GmY3tBJiyz
+pXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZhuJaJfqZ6VbT
+o4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsG
+A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt
+Yml0ggQBjLqBMB0GA1UdDgQWBBTRnChHSWbQYwnJC62n2zu5Njd03zAKBggqhQMH
+AQEDAgNBAB41oijaXSEn58l78y2rhxY35/lKEq4XWZ70FtsNlVxWATyzgO5Wliwn
+t1O4GoZsxx8r6T/i7VG65UNmQlwdOKQ=
+-----END CERTIFICATE-----
diff --git a/tcl_tests/tc26_cms/sender256_key.pem b/tcl_tests/tc26_cms/sender256_key.pem
new file mode 100644 (file)
index 0000000..3bac374
--- /dev/null
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQg6HfztrYQ
+Y/WOBUo0ORFCMsUWevdvbLfDx3iZRA6BIAs=
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/tc26_cms/sender512_cert.pem b/tcl_tests/tc26_cms/sender512_cert.pem
new file mode 100644 (file)
index 0000000..6a9cd39
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICNjCCAeOgAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD
+VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQwgaowIQYIKoUD
+BwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwOBhAAEgYC0i7davCkOGGVcYqFP
+tS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDPs2Sqa13ZN+Ts
+/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo6xGunecH1/G4
+hMts9HYLnxbwJDMNVGuIHV6gzqOBhTCBgjBhBgNVHQEEWjBYgBSA2Qz3mfhmTZNT
+iY7AnnEtp6cxEqE6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6
+IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQUK+l9HAscONGx
+zCcRpxRAmFHvlXowCgYIKoUDBwEBAwIDQQAbjA0Q41/rIKOOvjHKsAsoEJM+WJf6
+/PKXg2JaStthmw99bdtwwkU/qDbcje2tF6mt+XWyQBXwvfeES1GFY9fJ
+-----END CERTIFICATE-----
diff --git a/tcl_tests/tc26_cms/sender512_key.pem b/tcl_tests/tc26_cms/sender512_key.pem
new file mode 100644 (file)
index 0000000..8acf4d7
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MGgCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRAEWkl+ebl
+sHWs86SNgRKqSxMOgGhbvR/uZ5/WWfdNG1axvUwVhpcXIxDZUmzQuNzqJBkseI7f
+5/JjXyTFRF1a+Q==
+-----END PRIVATE KEY-----
diff --git a/tcl_tests/tc26_cms/signed_a111.pem b/tcl_tests/tc26_cms/signed_a111.pem
new file mode 100644 (file)
index 0000000..1e2b0bc
--- /dev/null
@@ -0,0 +1,25 @@
+-----BEGIN CMS-----
+MIIENwYJKoZIhvcNAQcCoIIEKDCCBCQCAQExDDAKBggqhQMHAQECAzA7BgkqhkiG
+9w0BBwGgLgQsyu7t8vDu6/zt++kg7/Do7OXwIOTr/yDx8vDz6vLz8PsgU2lnbmVk
+RGF0YS6gggI6MIICNjCCAeOgAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYD
+VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i
+aXQwHhcNMDEwMTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRU
+SzI2MSowKAYDVQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQw
+gaowIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwOBhAAEgYC0i7da
+vCkOGGVcYqFPtS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDP
+s2Sqa13ZN+Ts/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo
+6xGunecH1/G4hMts9HYLnxbwJDMNVGuIHV6gzqOBhTCBgjBhBgNVHQEEWjBYgBSA
+2Qz3mfhmTZNTiY7AnnEtp6cxEqE6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMT
+HkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQU
+K+l9HAscONGxzCcRpxRAmFHvlXowCgYIKoUDBwEBAwIDQQAbjA0Q41/rIKOOvjHK
+sAsoEJM+WJf6/PKXg2JaStthmw99bdtwwkU/qDbcje2tF6mt+XWyQBXwvfeES1GF
+Y9fJMYIBlDCCAZACAQEwQDA4MQ0wCwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBU
+SzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQCBAGMuoQwCgYIKoUDBwEBAgOgga0w
+GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkwMzIw
+MTk1NTIyWjAiBgkqhkiG9w0BCWIxFQQTU2lnbmVkIGF0dHIncyB2YWx1ZTBPBgkq
+hkiG9w0BCQQxQgRAUdPHEukF5BIfo9DoQIMdnB0ZLkzq0RueEUZSNv07A7C+GKWi
+G62fueArg8uPCHPTUN6d/42p33fgMkEwH7f7cDAKBggqhQMHAQEBAgSBgGUnVka8
+FvTlClmOtj/FUUacBdE/nEBeMLOO/535VDYrXlftPE6zQf/4ghS7TQG2VRGQ3GWD
++L3+W09A7d5uyyTEbvgtdllUG0OyqFwKmJEaYsMin87SFVs0cn1PGV1fOKeLluZa
+bLx5whxd+mzlpekL5i6ImRX+TpERxrA/xSe5
+-----END CMS-----
diff --git a/tcl_tests/tc26_cms/signed_a121.pem b/tcl_tests/tc26_cms/signed_a121.pem
new file mode 100644 (file)
index 0000000..fe6d6b7
--- /dev/null
@@ -0,0 +1,19 @@
+-----BEGIN CMS-----
+MIIDAQYJKoZIhvcNAQcCoIIC8jCCAu4CAQExDDAKBggqhQMHAQECAjA7BgkqhkiG
+9w0BBwGgLgQsyu7t8vDu6/zt++kg7/Do7OXwIOTr/yDx8vDz6vLz8PsgU2lnbmVk
+RGF0YS6gggH3MIIB8zCCAaCgAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYD
+VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i
+aXQwHhcNMDEwMTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRU
+SzI2MSowKAYDVQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQw
+aDAhBggqhQMHAQEBATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABECWKQ0TYllq
+g4GmY3tBJiyzpXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZ
+huJaJfqZ6VbTo4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzES
+oTowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4x
+MC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBTRnChHSWbQYwnJC62n2zu5Njd0
+3zAKBggqhQMHAQEDAgNBAB41oijaXSEn58l78y2rhxY35/lKEq4XWZ70FtsNlVxW
+ATyzgO5Wliwnt1O4GoZsxx8r6T/i7VG65UNmQlwdOKQxgaIwgZ8CAQEwQDA4MQ0w
+CwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1
+Ni1iaXQCBAGMuoIwCgYIKoUDBwEBAgIwCgYIKoUDBwEBAQEEQC6jZPA59szL9FiA
+0wC71EBE42ap6gKxklT800cu2FvbLu972GJYNSI7+UeanVU37OVWyenEXi2E5HkU
+94kBe8Q=
+-----END CMS-----
diff --git a/tcl_tests/test.tcl b/tcl_tests/test.tcl
new file mode 100644 (file)
index 0000000..8e2b45a
--- /dev/null
@@ -0,0 +1,452 @@
+# -*- coding: cp1251 -*-
+# Установка номера тестового ПРА
+
+namespace eval vizir {
+       set regnumPRA 0000000000000001
+}      
+
+#
+#
+# Собственно тестовый фреймворк
+
+
+
+namespace eval test {
+       # Уровень логгинга по умолчанию. Может быть переопределен явным
+       # присваиванием перед созданием контекста. Действует на контексты
+       # созданные makeCtx, makeCtx2 и threecontexts.
+       # Задание -logminpriority в test::ctxParams имеет приоритет.
+       set logLevel 3  
+       # Переменная хранящая имя динамической библиотеки для userlib
+       variable userlib {}
+       # Чтобы timestamp была определена всегда
+       variable timestamp [clock seconds]
+       proc findUserLib {} {
+               variable userlib
+               if {$::tcl_platform(platform)!="dos"} {
+                       set dirlist  [list [file dirname [info script]]\
+                               [file dirname [info nameofexecutable]]]
+                       if {$::tcl_platform(platform) == "windows"} {
+                               lappend dirlist\
+                               [file normalize [file join [file dirname [info script]] ..  obj_mid.w32]]\
+                               [file normalize [file join [file dirname [info script]] ..  obj_mid.w32]]
+                       } elseif {$::tcl_platform(os) == "Linux"} {
+                               lappend dirlist\
+                               [file normalize [file join [file dirname [info script]] ..  obj_sid.lnx]]
+                       } elseif {$::tcl_platform(os) == "SunOS"} {
+                               if {$::tcl_platform(wordSize) == 8} {
+                                       set for s64
+                               } elseif {$::tcl_platform(byteOrder) == "littleEndian"} {
+                                       set for s86
+                               } else {
+                                       set for s32
+                               }
+                               lappend dirlist\
+                               [file normalize [file join [file dirname [info script]] ..  obj_sid.$for]]
+                       }        
+                       foreach dir $dirlist {
+                       set userlib_file [file join  $dir  usermci[info sharedlibextension]]
+                               if {[file exists $userlib_file]} {
+                                       break
+                               }       
+                       }       
+                       if {![file exists $userlib_file]} {
+                               error "No usable userlib found in $dirlist"
+                       }       
+                       set userlib [list -userlib $userlib_file]
+               } else {
+                       set userlib {}
+               }       
+       }       
+       #
+       # 
+       #
+       # Вызывается в начале тестового скрипта. Инициализирует необходимые
+       # переменные пакета, открывает лог и пишет в него заголовок
+       # Параметры name - заголовок тестового скрипта.
+       #  
+       # Побочные эффекты - создается <имя-скрипта>.log
+       #
+       proc start_tests {name} {
+               variable suffix
+               if {![info exists suffix]} {
+                       set binary [file rootname [file tail [info nameofexecutable]]]
+                       if {$binary != "tclsh"} {
+                               set suffix "_[string range [file tail [info nameofexecutable]] 0 2]"
+                       } else {
+                               set suffix ""
+                       }       
+               }
+               variable logname [file rootname [file tail [info script]]]$suffix.log
+               variable no 0 ok 0 failed 0 p_skip 0 c_skip 0 t_name $name logchannel [open $logname w] tempfiles {}
+               if {![catch {package present Vizir}]} {
+                       findUserLib
+               }       
+               puts [format [rus "=========== Группа тестов: %s ================="] [rus $name]]
+               puts $::test::logchannel [format [rus "Группа тестов \"%s\""] $name]
+       }       
+       #
+       # Завершает выполнение теста и выводит отчет
+       # Вызывает exit 
+       #
+       proc end_tests {} {
+               variable no
+               variable ok
+               variable failed
+               variable p_skip
+               variable t_name
+               variable c_skip
+               variable logname
+               variable tempfiles
+               variable suffix
+               puts "==================================================="
+               puts [format [rus "Всего %d тестов. Выполнено %d успешно, %d неуспешно"] $no $ok $failed]
+               if {$p_skip || $c_skip} {
+                       puts [format [rus "Пропущено: %d на данной платформе %d из-за невыполнения других тестов"] $p_skip $c_skip]
+               }
+               if {$failed} {
+                       puts [format [rus "Смотри более подробную информацию в %s"] $logname]
+               } 
+               set test_id [file rootname [file tail [info script]]]$suffix
+               set stat [open "stats" a]
+               fconfigure $stat -encoding cp1251
+               puts $stat [list $test_id [rus $t_name] $no $ok $failed $p_skip $c_skip] 
+               close $stat
+               if {!$failed} { 
+                       foreach file $tempfiles {
+
+                               if [info exists $file] {puts [test_log] "Deleting $file"
+                                  file delete $file}
+                       }       
+               }       
+       }
+   #
+   # Вовзращает идентификатор канала, куда пишется лог тестов.
+   # Рекомендуется назначать его в качестве -logchannel создаваемым
+   # контекстам чтобы вся выдача была в одном месте
+   # 
+   proc test_log {} {
+               variable logchannel
+               return $logchannel
+       }
+       #
+       # Собственно тест 
+       #   Параметры
+       #   1. Название теста
+       #   2. Код (рекомендуется писать {
+       #       код
+       #     }
+       #   3. Ожидаемый результат выполнения - 0 успешно 1 - ошибка. Варианты
+       #     больше 1 (TCL_BREAK, TCL_CONTINUE и TCL_RETURN) возможны, но вряд
+       #     ли интересны
+       #   4. Ожидаемый возвращаемый результат
+       #      Если предыдущий параметр 0, результат сравнивается на точное
+       #      совпадение, если 1 - результат - регексп, которому должно
+       #      удовлетворять сообщение об ошибке.
+       proc test args {
+               array set opts {}
+               variable tempfiles
+               variable timestamp
+               while {[string match -* [lindex $args 0]]} {
+                       set key [lindex $args 0]
+                       set val [lindex $args 1]
+                       set args [lrange $args 2 end]
+                       set opts($key) $val
+               }
+           foreach {message code exitStatus expectedResult} $args break
+               global errorInfo 
+               if {[info exists opts(-platform)] && [lsearch -exact $opts(-platform) $::tcl_platform(platform)]==-1} {
+                       logskip $message "platform"
+                       return
+               }
+               if {[info exists opts(-platformex)] && ![uplevel expr $opts(-platformex)]} {
+                       logskip $message "platform"
+                       return
+               }       
+               if {[info exists opts(-skip)] && [uplevel expr $opts(-skip)]} {
+                       logskip $message "prereq" 
+                       return
+               }       
+               if {[info exists opts(-fixme)] && [uplevel expr $opts(-fixme)]} {
+                       logmiss $message "FIXME" 
+                       return
+               }       
+               if {[info exists opts(-createsfiles)]} {
+                       foreach file $opts(-createsfiles) {
+                               lappend tempfiles $file
+                               if {[file exists $file]} {file delete $file}
+                       }
+               }
+               if {[info exists opts(-createsvars)]} {
+                       foreach var $opts(-createsvars) {
+                               uplevel  "if {\[info exists $var\]} {unset $var}"
+                       }
+               }       
+               logbegin $message
+               set teststart [clock seconds]
+               set status [catch {uplevel $code} result]
+               set testend [clock seconds]
+               if {$teststart == $testend} {
+                       set timestamp $teststart
+               } else {
+                       # Handle negative intervals correctly
+                       if {$teststart > $testend} {
+                               set timestamp "$testend+[expr $teststart-$testend]"
+                       } else {        
+                               set timestamp "$teststart+[expr $testend-$teststart]"
+                       }
+               }       
+               if {$status!=$exitStatus || ($status==1?![regexp --\
+                       [rus $expectedResult] $result]:([info exists opts(-time)]?\
+                   ![listcompare $result $expectedResult $opts(-time)]:\
+                       [string compare "$result" "$expectedResult"]))} {
+                       logend "failed"
+                       if {$status == 1} {
+                               set expectedResult [rus $expectedResult]
+                       }       
+                       log   "Code:----$code---------------"
+                       log     "Expected status $exitStatus got $status"
+                       log   "Expected result: [list $expectedResult]"
+                       log     "     Got result: [list $result]"
+                       if {$status == 1} {
+                               log "errorCode = $::errorCode"
+                       }       
+               } else {
+                       logend "ok"
+               }       
+       }
+#
+# Внутренние (неэкспортируемые)процедуры
+#
+#
+
+#
+# Сравнение списков с учетом того что некоторые элементы могут быть
+# метками времени, которые проверяются с точностью +-секунда
+# Параметр time - список, каждый элемент которого является индексом
+# элемента в списке, либо списком индексов во вложенных списках
+# 
+proc listcompare {list1 list2 time} {
+       foreach e $time {
+               if {[llength $e]>1} {
+                       lappend a([lindex $e 0]) [lrange $e 1 end]
+               } else {
+                       set a($e) {}
+               }       
+       }
+       if {[llength $list1] !=[llength $list2]} {
+               return 0
+       }       
+       set i 0
+       foreach e1 $list1 e2 $list2 {
+               if {![info exists a($i)]} {
+                       if {[string compare $e1 $e2]!=0} {
+                               return 0
+                       }
+               } elseif {[llength $a($i)]} {
+                       if {![listcompare $e1 $e2 $a($i)]} {
+                               return 0
+                       }
+               } else {
+                       if {$e2 == "::test::timestamp"} {
+                               set e2 $::test::timestamp
+                       }       
+                       if {[regexp {^([[:digit:]]+)\+([[:digit:]]+)$} $e2 m start delta]} {
+                               if {$e1<$start || $e1 >$start+$delta} {
+                                       return 0
+                               }
+                       } elseif {abs($e1-$e2)>1} {
+                               return 0
+                       }
+               }
+               incr i
+       }       
+       return 1
+}
+# Перекодирует строку из кодировки скрипта (assumed 1251)
+# в текущую системную
+
+if {[encoding system] == "utf-8" } {
+
+proc rus {string} {
+       return [encoding convertfrom cp1251 $string]
+}
+
+} else {
+
+proc rus {string} "
+       return \[encoding convertfrom cp1251 \[encoding convertto [encoding system] \$string\]\]
+"
+
+}
+   #
+   # Пишет строку в лог
+   #
+   proc log {message} {
+               variable logchannel
+               puts $logchannel $message
+       }
+       #
+       # Вызывается при начале теста
+       # 
+       proc logbegin {testname} {
+               variable no
+               variable curtest
+               incr no
+               puts -nonewline [rus [format "Тест%5d: %-60s:" $no [string range $testname 0 59]]]
+               flush stdout
+               set curtest $testname
+               log [rus "Тест $no: $testname start"]
+       }
+       #
+       # Вызывается при пропуске теста
+       #
+       proc logskip {testname reason} {
+               variable no
+               variable p_skip
+               variable c_skip
+               puts "[rus [format "Тест%5d: %-60s:" $no [string rang $testname 0 59]]]skipped "
+               log "[rus "Тест $no: skipped "][expr {$reason=="platform"?"on
+               the platform $::tcl_platform(platform)":"due to failed prerequisites"}]:[rus $testname]" 
+               incr no
+               if {$reason == "platform"} {
+                       incr p_skip
+               } else {
+                       incr c_skip
+               }       
+       }
+       
+       #
+       # Вызывается при игнорировании теста
+       #
+       proc logmiss {testname reason} {
+               variable no
+               variable c_skip
+               puts "[rus [format "Тест%5d: %-60s:" $no [string rang $testname 0 59]]]missed "
+               log "[rus "Тест $no: missed "][expr {$reason=="platform"?"on
+               the platform $::tcl_platform(platform)":"by reason: $reason"}]:[rus $testname]" 
+               incr no
+               incr c_skip
+       }
+
+       #
+       # Вызывается конце теста и с параметром ok или failed
+       #
+       proc logend {status} {
+               variable no
+               variable curtest
+               variable $status
+               incr $status
+               puts $status
+               log [rus "Тест $no: $curtest ends $status"]
+       }
+       
+       #####################################################################
+       # Вспомогательные процедуры, не специфичные для тестируемого
+       # приложения
+       #####################################################################
+
+       #
+       # Записывает  данные из data в файл name. По умолчанию пишет в
+       # текущей системной кодировке. Можно указать кодировку явно третьим
+       # аргументом
+       #
+       proc makeFile {name data {encoding {}}} {
+               set f [open $name w]
+               setFileEncoding $f $encoding
+               puts -nonewline $f $data 
+               close $f
+       }       
+       proc setFileEncoding {f encoding} {
+               if {[string length $encoding]} {
+                       if {"$encoding" == "binary"} {
+                               fconfigure $f -translation binary
+                       } else {        
+                               fconfigure $f -encoding $encoding
+                       }       
+               }
+       }       
+#
+# Возвращает содeржимое файла 
+#
+
+proc getFile {filename {encoding {}}} {
+       set f [open $filename]
+       setFileEncoding $f $encoding
+       set data [read $f]
+       close $f
+       return $data
+}      
+#
+# Возвращает содержимое бинарного файла. Для совместимости со старыми
+# тестами
+#
+proc getfile {filename} {
+       return [getFile $filename binary]
+}      
+       # 
+       # Зачитывает указанный файл, удаляет его и возвращает содержимое.
+       # По умолчанию читает файл в текущей системной кодировке. Можно
+       # указать кодировку явно вторым аргументом.
+       #
+
+       proc readAndDel {name {encoding {}}} {
+               set f [open $name]
+               setFileEncoding $f $encoding
+               set data [read $f]
+               close $f
+               file delete $name
+               return $data
+       }       
+
+
+       #
+       # Защищает файл от записи средствами операционной системы
+       # denywrite filename ?boolean?
+       # Если boolean не указан, или он true, файл становится read-only
+       # Если указан - readwrite (для владельца. Впрочем для не-владельца все
+       # равно не сработает)
+       #
+       proc denyWrite {filename {deny 1}} {
+               global tcl_platform
+               if {$tcl_platform(platform) == "unix"} {
+                       set cur_attr [file attributes $filename -permissions]
+                       if {$deny} {
+                               set new_attr [expr {$cur_attr &~ 0200}]
+                       } else {
+                               set new_attr [expr {$cur_attr | 0200}]
+                       }       
+                       file attributes $filename -permissions $new_attr
+               } else {
+                       file attributes $filename -readonly $deny 
+               }
+       }       
+       #
+       # Записывает в лог 16-ричный дамп указанной переменной
+       #
+
+       proc hexdump {data } {
+               while {[string length $data]} {
+                       set block [string range $data 0 15] 
+                       set data [string replace $data 0 15]
+                       binary scan [encoding convertto $block] c* list
+                       set line ""
+                       set i 0
+                       foreach code $list {
+                               append line [format "%02x " [expr $code>=0?$code:$code +256]]
+                               if {[incr i]%4==0} {
+                                       append line "| "
+                               }
+                       }
+                       append line [string repeat " " [expr 56-[string length $line]]]
+                       regsub -all "\[\0-\37\]" $block . printable
+                       append line [rus $printable]
+                       log $line
+               }
+       }       
+       namespace export test start_tests end_tests test_log rus log\
+       makeFile readAndDel hexdump denyWrite getFile getfile
+}      
+namespace import ::test::*
+
+package provide test 0.2
diff --git a/tcl_tests/tmpl.try b/tcl_tests/tmpl.try
new file mode 100644 (file)
index 0000000..731b4ba
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/tclsh
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду dgst" 
+end_tests
diff --git a/tcl_tests/ts.try b/tcl_tests/ts.try
new file mode 100644 (file)
index 0000000..fe8fa04
--- /dev/null
@@ -0,0 +1,305 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+set env(LC_TIME) C
+if [file exists tsa.serial] {
+       file delete tsa.serial
+}
+set testname [file rootname [file tail $::argv0]]
+
+#
+# Formats 64 hex digits into format 
+#
+proc format_hash {hash} {
+       # Split hash into list of two-digit hexadecimal numbers
+       set list [regexp -all -inline {[[:xdigit:]]{2}} $hash]
+       for {set i 0} {$i<[llength $list]} {incr i 16} {
+               append out [format "    %04x - " $i] 
+               set hex [join [lrange $list $i [expr $i+15]] " "]
+               if {[string length $hex]>24} {
+                       set hex [string replace  $hex 23 23 "-"] 
+               }       
+               append out $hex [string repeat " " [expr 50-[string length $hex]]]
+               foreach char [lrange $list $i [expr $i+15]] {
+                   set n [scan $char "%x"]
+                       if {$n>=32 && $n <=126 } {
+                               append out [format %c $n]
+                       } else {
+                               append out "."
+                       }
+               }       
+               append out "\n"
+       }       
+       # Chop newline from last line
+       return [string trim $out "\n"]
+}
+#
+# Replace Nonce with equvalent number of X-es because we cannot 
+# predict nonce for comparing output, and chop out STDERR
+# If output contains timestamp, extract it, replace with word
+# "extracted" and return two-element list where element 0 is modified
+# output and element 1 is timestamp in unix time
+#
+proc cleanup_print {output} {
+       set data  [regsub {STDERR CONTENTS:.*$} [regsub {Nonce: 0x[[:xdigit:]]+} $output  {Nonce: 0xXXXXXXXXXXXXXXXX}] {}]
+       if {[regexp "\nTime stamp: (\[^\n\]+)\n" $data -> time]} {
+               return [list [regsub "\nTime stamp: (\[^\n\]+)\n" $data "\nTime stamp: extracted\n"] [clock scan $time]]
+       } else {
+               return $data
+       }       
+}
+
+start_tests "Тесты на timestamping protocol" 
+
+test "Creating CA 2001" {
+       makeCA ${testname}CA gost2001:A
+} 0 1
+
+test "Creating CA 2012" {
+       makeCA
+} 0 1
+
+set serial_num 0
+
+if {[info exists env(ALG_LIST)]} {
+       set alg_list $env(ALG_LIST)
+} else {
+       switch -exact [engine_name] {
+               "ccore" {set alg_list {gost2001:A gost2012_256:A gost2012_512:A}}
+               "open" {set alg_list {gost2001:A gost2012_256:A gost2012_512:A}}
+       }
+}
+
+foreach alg $alg_list {
+       set alg_fn [string map {":" "_"} $alg]
+       set username U_tsa_$alg_fn
+       set hash_alg [alg_hash $alg]
+       switch -glob $alg {
+               gost2012* {set ::test::ca ${testname}CA-2012}
+               * {set ::test::ca ${testname}CA}
+       }
+
+test "Creating Timestamping authority certificate" {
+       makeRegisteredUser $username $alg CN "Timestamping authority $alg" \
+       extensions "keyUsage=digitalSignature,nonRepudiation\nextendedKeyUsage=critical,timeStamping"
+       openssl "verify -CAfile $::test::ca/cacert.pem -purpose timestampsign $username/cert.pem"
+} 0 "$username/cert.pem: OK\n"
+
+test "creating TSA configuration file" {
+       makeFile tsa.cnf "\[ tsa \]
+default_tsa = tsa_section
+\[ tsa_section \]
+serial = [pwd]/tsa.serial
+digests=[hash_short_name $hash_alg]
+default_policy = 1.2.3.4
+other_policies = 1.2.3.4.5,1.2.3.4.6
+signer_digest = md_gost94
+"
+} 0 ""
+test "Creating request with [hash_short_name $hash_alg], no cert request, no policy" {
+       makeFile testdata [string repeat "Test data for timestamp\n" 100]
+       set hash1 [regsub {^[^=]+= } [openssl "dgst -[hash_short_name $hash_alg] testdata"] {}]
+       set sha1hash1 [regsub {^[^=]+= } [openssl "dgst -sha1 testdata"] {}]
+       openssl "ts -query -[hash_short_name $hash_alg] -data testdata -out req1.tsq"
+       file exists req1.tsq
+} 0 1
+test "Printing request 1" {
+       cleanup_print [openssl "ts -query  -text -in req1.tsq"]
+} 0 "Version: 1
+Hash Algorithm: [hash_long_name $hash_alg]
+Message data:
+[format_hash $hash1]
+Policy OID: unspecified
+Nonce: 0xXXXXXXXXXXXXXXXX
+Certificate required: no
+Extensions:
+"
+
+test "Creating reply for request1" {
+       incr serial_num
+       openssl "ts -reply -config tsa.cnf -queryfile req1.tsq -signer $username/cert.pem -inkey $username/seckey.pem -out resp1.tsr -[hash_short_name $hash_alg]"
+       file exists resp1.tsr
+} 0 1
+       set creation_time1 $::test::timestamp 
+test -time 1  "printing reply 1" {
+       cleanup_print [openssl "ts -reply -text -in resp1.tsr"]
+} 0 [list  "Status info:
+Status: Granted.
+Status description: unspecified
+Failure info: unspecified
+
+TST info:
+Version: 1
+Policy OID: 1.2.3.4
+Hash Algorithm: [hash_long_name $hash_alg]
+Message data:
+[format_hash $hash1]
+Serial number: 0x[format "%02X" $serial_num]
+Time stamp: extracted
+Accuracy: unspecified
+Ordering: no
+Nonce: 0xXXXXXXXXXXXXXXXX
+TSA: unspecified
+Extensions:
+" $creation_time1]
+
+test "Verifying reply against query file" {
+       grep "Verification" [openssl "ts -verify -in resp1.tsr -queryfile req1.tsq -untrusted $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+test "Verifying reply against data file" {
+       grep "Verification" [openssl "ts -verify -in resp1.tsr -data testdata -untrusted $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+
+test "Verifying reply against other data file" {
+       makeFile testdata2 [string repeat "Test data for timestamp 2\n" 100]
+       set hash2 [regsub {^[^=]+= } [openssl "dgst -[hash_short_name $hash_alg] testdata2"] {}]
+       openssl "ts -verify -in resp1.tsr -data testdata2 -untrusted $username/cert.pem -CAfile $::test::ca/cacert.pem"
+} 1 "message imprint mismatch"
+
+test "Verifying reply against explicit hash value" {
+       grep "Verification" [openssl "ts -verify -in resp1.tsr -digest $hash1 -untrusted $username/cert.pem -CAfile $::test::ca/cacert.pem"]
+
+} 0 "Verification: OK\n"
+
+test "Creating request 2 with [hash_short_name $hash_alg], cert requested, no policy" {
+       openssl "ts -query -[hash_short_name $hash_alg] -data testdata -cert -out req2.tsq"
+       file exists req2.tsq
+} 0 1
+
+test "Printing request 2" {
+       cleanup_print [openssl "ts -query  -text -in req2.tsq"]
+} 0 "Version: 1
+Hash Algorithm: [hash_long_name $hash_alg]
+Message data:
+[format_hash $hash1]
+Policy OID: unspecified
+Nonce: 0xXXXXXXXXXXXXXXXX
+Certificate required: yes
+Extensions:
+"
+
+test "Replying to request 2" {
+       incr serial_num
+       openssl "ts -reply -config tsa.cnf -queryfile req2.tsq -signer $username/cert.pem -inkey $username/seckey.pem -out resp2.tsr -[hash_short_name $hash_alg]"
+       file exists resp2.tsr
+} 0 1
+set creation_time2 $::test::timestamp
+
+test -time 1 "Printing reply 2" {
+       cleanup_print [openssl "ts -reply -text -in resp2.tsr"]
+} 0 [list "Status info:
+Status: Granted.
+Status description: unspecified
+Failure info: unspecified
+
+TST info:
+Version: 1
+Policy OID: 1.2.3.4
+Hash Algorithm: [hash_long_name $hash_alg]
+Message data:
+[format_hash $hash1]
+Serial number: 0x[format "%02X" $serial_num]
+Time stamp: extracted
+Accuracy: unspecified
+Ordering: no
+Nonce: 0xXXXXXXXXXXXXXXXX
+TSA: unspecified
+Extensions:
+" $creation_time2]
+
+test "Verifying reply2 against request file" {
+       grep "Verification" [openssl "ts -verify -in resp2.tsr -queryfile req2.tsq -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+test "Verifying reply2 against data file" {
+       grep "Verification" [openssl "ts -verify -in resp2.tsr -data testdata -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+test "Verifying reply2 against explicit digest" {
+       grep "Verification" [openssl "ts -verify -in resp2.tsr -digest $hash1 -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+test "Verifying reply2 against request 1" {
+       grep "Verification" [openssl "ts -verify -in resp2.tsr -queryfile req1.tsq -CAfile $::test::ca/cacert.pem"]
+} 1 "nonce mismatch"
+
+test "Creating request 3 with sha1 digest" {
+       openssl "ts -query -sha1 -data testdata -cert -out req3.tsq"
+       file exists req3.tsq
+} 0 1
+
+
+test "Printing request 3" {
+       cleanup_print [openssl "ts -query  -text -in req3.tsq"]
+} 0 "Version: 1
+Hash Algorithm: sha1
+Message data:
+[format_hash $sha1hash1]
+Policy OID: unspecified
+Nonce: 0xXXXXXXXXXXXXXXXX
+Certificate required: yes
+Extensions:
+"
+
+test "Replying to request 3 (with badAlg status)" {
+       set creation_time3 [clock format [clock seconds] -gmt y -format "%B %d %H:%M:%S %Y GMT"]
+       openssl "ts -reply -config tsa.cnf -queryfile req3.tsq -signer $username/cert.pem -inkey $username/seckey.pem -out resp3.tsr -[hash_short_name $hash_alg]"
+       file exists resp3.tsr
+} 0 1
+
+test  "Printing reply 3" {
+       cleanup_print [openssl "ts -reply -text -in resp3.tsr"]
+} 0 "Status info:
+Status: Rejected.
+Status description: Message digest algorithm is not supported.
+Failure info: unrecognized or unsupported algorithm identifier
+
+TST info:
+Not included.
+"
+
+test "Verifying response 3 against request file" {
+       openssl "ts -verify -in resp3.tsr -queryfile req3.tsq -CAfile $::test::ca/cacert.pem"
+} 1 "status code: rejection, status text: Message digest algorithm is not supported., failure codes: badAlg"
+
+
+
+test "Creating request 4 with specific (valid) policy" {
+       openssl "ts -query -[hash_short_name $hash_alg] -data testdata -tspolicy 1.2.3.4.5 -cert -out req4.tsq"
+       file exists req4.tsq
+} 0 1
+
+test "Replying to request 4" {
+       incr serial_num
+       openssl "ts -reply -config tsa.cnf -queryfile req4.tsq -signer $username/cert.pem -inkey $username/seckey.pem -out resp4.tsr -[hash_short_name $hash_alg]"
+       file exists resp4.tsr
+} 0 1
+
+test "Verifying reply 4 against request file" {
+       grep "Verification" [openssl "ts -verify -in resp4.tsr -queryfile req4.tsq -CAfile $::test::ca/cacert.pem"]
+} 0 "Verification: OK\n"
+
+
+test "Creating request 5 with specific (invalid) policy" {
+       openssl "ts -query -[hash_short_name $hash_alg] -data testdata -tspolicy 1.2.3.4.9 -cert -out req5.tsq"
+       file exists req5.tsq
+} 0 1
+
+test "Replying to request 5" {
+       openssl "ts -reply -config tsa.cnf -queryfile req5.tsq -signer $username/cert.pem -inkey $username/seckey.pem -out resp5.tsr -[hash_short_name $hash_alg]"
+       file exists resp5.tsr
+} 0 1
+
+
+test "Verifying reply 5" {
+       openssl "ts -verify -in resp5.tsr -queryfile req5.tsq -CAfile $::test::ca/cacert.pem"
+} 1 "status code: rejection, status text: Requested policy is not supported., failure codes: unacceptedPolicy"
+
+
+}
+
+end_tests
diff --git a/tcl_tests/vn4.ciphers b/tcl_tests/vn4.ciphers
new file mode 100644 (file)
index 0000000..c6cd506
--- /dev/null
@@ -0,0 +1,15 @@
+gost2001:XA {
+       GOST2001-GOST89-GOST89 v-vn4-01.vm.cryptocom.ru:443:iis
+       GOST2012-GOST8912-GOST8912 v-vn4-01.vm.cryptocom.ru:443:iis
+#      GOST2001-NULL-GOST94 v-vn4-01.vm.cryptocom.ru:443:iis
+#      GOST2012-NULL-GOST12 v-vn4-01.vm.cryptocom.ru:443:iis
+}
+gost2012_256:XA {
+       GOST2012-GOST8912-GOST8912 v-vn4-12S.vm.cryptocom.ru:443:iis
+#      GOST2012-NULL-GOST12 v-vn4-12S.vm.cryptocom.ru:443:iis
+}
+gost2012_512:A {
+       GOST2012-GOST8912-GOST8912 v-vn4-12L.vm.cryptocom.ru:443:iis
+#      GOST2012-NULL-GOST12 v-vn4-12L.vm.cryptocom.ru:443:iis
+}
+
diff --git a/tcl_tests/wcli.try b/tcl_tests/wcli.try
new file mode 100644 (file)
index 0000000..35ed578
--- /dev/null
@@ -0,0 +1,150 @@
+#!/usr/bin/tclsh
+# -*- coding: cp1251 -*-
+lappend auto_path [file dirname [info script]]
+package require ossltest
+
+#Первый параметр задает используемый сайферсьют.
+#Вариант p0 не предназначена для использования в автоматических тестах, так как
+#мы не можем программно оценить корректность результата. При использовании
+#этого варианта тесты будут гарантированно фейлиться, поэтому использовать 
+#его следует только для ручного запуска и внимательно читать логи.
+array set cipher_name {
+       p8k GOST2012-KUZNYECHIK-KUZNYECHIKOMAC 
+       p8m GOST2012-MAGMA-MAGMAOMAC 
+       p2 GOST2012-GOST8912-GOST8912
+       p1 GOST2001-GOST89-GOST89
+       p20 GOST2012-NULL-GOST12
+       p10 GOST2001-NULL-GOST94
+       p0 {}  
+}
+proc cipher_openssl {sn} {return $::cipher_name($sn)}
+proc cipher_command_line_option {sn} {
+       if {$sn == "p0"} {
+               return $::cipher_name($sn)
+       } else {
+               return "-cipher $::cipher_name($sn)"
+       }
+}
+       
+proc ciphers_usage {} {
+       global cipher_name
+       set res {}
+       foreach name [array names cipher_name] {
+               append res [format "\t%-3s - %s\n" $name $cipher_name($name)]
+       }
+       return $res
+}
+
+# Второй параметр задает четвёрку значений:
+#- алгоритм ключа сервера
+#- параметры ключа сервера
+#- список имен клиентских сертификатов
+#- алгоритм ключа УЦ 
+array set alg_name {
+       5xa {gost2012_512 A {Xchg512A Sign512A} gost2012_512}
+       2xa {gost2012_256 XA {Xchg256A Sign256A} gost2012_256} 
+       1xa {gost2001 XA {XchgA SignA} gost2001}
+}
+proc alg_alg {sn} {return [lindex $::alg_name($sn) 0]}
+proc alg_crtdir {sn} {return [format "srv_%s_%s" [lindex $::alg_name($sn) 0] [lindex $::alg_name($sn) 1]]}
+proc alg_openssl {sn} {return [format "%s:%s" [lindex $::alg_name($sn) 0] [lindex $::alg_name($sn) 1]]}
+proc alg_certid_list {sn} {return [lindex $::alg_name($sn) 2]}
+proc alg_ca {sn} {return [lindex $::alg_name($sn) 3]}
+proc algs_usage {} {
+       global alg_name
+       set res {}
+       foreach name [array names alg_name] {
+               append res [format "\t%-3s - %s:%s\n" $name [lindex $alg_name($name) 0] [lindex $alg_name($name) 1]]
+       }
+       return $res
+}
+
+if {$argc < 1 || ![regexp {^([^-]+)-([^-]+)-([^-]+)-(.+)$} [lindex $argv 0] -> cipher alg tls host]} {
+       puts stderr "Usage $argv0 cipher-alg-tlsver-hostname \[s_server-option\]"
+       puts stderr "cipher:\n[ciphers_usage]"
+       puts stderr "alg:\n[algs_usage]"
+       puts stderr "tlsver: -tls* s_server option"
+       exit 1
+}
+set test::suffix "-$cipher-$alg-$tls-$host[lindex $argv 1]" 
+if {![regexp @ $host]} {
+       set host build@$host
+}      
+
+set CAhost lynx.lan.cryptocom.ru
+set CAprefix /cgi-bin/autoca 
+set mydir [file normalize [file dirname [info script]]]
+
+cd $::test::dir
+set http_tcl http.[info hostname].[clock seconds].[pid].tcl
+
+start_tests "CSP клиент ($cipher, $alg, $host) [lindex $argv 1]" 
+
+test  "Делаем копию http.tcl на $host" {
+       save_env2 {LD_LIBRARY_PATH OPENSSL_CONF}
+       catch {unset env(LD_LIBRARY_PATH)}
+       catch {unset env(OPENSSL_CONF)}
+       exec $env(CVS_RSH) $host "cat >$http_tcl" < $mydir/http.tcl
+       restore_env2 {LD_LIBRARY_PATH OPENSSL_CONF}
+       set copied 1
+} 0 1
+
+set crtdir [alg_crtdir $alg]
+
+test -platformex {![file exists $crtdir/cert.pem]} "Получаем сертификат HTTPS-сервера" {
+       if {![makeUser $crtdir [alg_openssl $alg] CN [info hostname]]} {
+               error "Request generation failed"
+       }
+       registerUserAtCA $crtdir $CAhost $CAprefix [alg_ca $alg]
+       file exists $crtdir/cert.pem
+} 0 1
+
+
+test -platformex {![file exists ca_[alg_ca $alg].pem]} "Получаем сертификат CA" {
+       getCAcert $CAhost $CAprefix [alg_ca $alg]
+       file exists ca_[alg_ca $alg].pem
+} 0 1
+
+
+custom_client "$env(CVS_RSH) $host tclsh $http_tcl" \
+       {LD_LIBRARY_PATH OPENSSL_CONF}
+
+set server_args [concat [cipher_command_line_option $cipher] \
+       [list -bugs -msg -cert $crtdir/cert.pem -key $crtdir/seckey.pem \
+       -CAfile ca_[alg_ca $alg].pem -www] -$tls [lindex $argv 1]]
+
+
+test -skip {![info exists copied]} "Сервер не требует сертификата" {
+       set list [client_server https://[info hostname]:4433 $server_args {}]
+       grep New, [lindex $list 0]
+} 0 "New, TLSv1/SSLv3, Cipher is [cipher_openssl $cipher]\n"
+
+
+test -skip {![info exists copied]} "Сервер требует сертификат, сертификата нет" {
+       set list [client_server \
+               [list https://[info hostname]:4433 no-such-cert-at-all] \
+               [concat $server_args {-Verify 2}] {}]
+       list [lindex $list 2] [lindex [split [lindex $list 1] " "] 0]
+} 0 [list 1 "0x80072f0c"]
+
+
+foreach alg_certid [alg_certid_list $alg] {
+       test -skip {![info exists copied]} \
+       "Сервер требует сертификат, клиент $alg_certid" {
+               set list [client_server \
+                       [list https://[info hostname]:4433 $alg_certid] \
+               [       concat $server_args {-Verify 2}]  {}]
+               grep New, [lindex $list 0]
+       } 0 "New, TLSv1/SSLv3, Cipher is [cipher_openssl $cipher]\n"
+}
+
+test "Удаляем копию http.tcl на $host" {
+       save_env2 {LD_LIBRARY_PATH OPENSSL_CONF}
+       catch {unset env(LD_LIBRARY_PATH)}
+       catch {unset env(OPENSSL_CONF)}
+       set rc [exec $env(CVS_RSH) $host rm -f $http_tcl]
+       restore_env2 {LD_LIBRARY_PATH OPENSSL_CONF}
+       set rc
+} 0 ""
+
+end_tests
diff --git a/tcl_tests/yarrowc.tcl b/tcl_tests/yarrowc.tcl
new file mode 100644 (file)
index 0000000..66a8153
--- /dev/null
@@ -0,0 +1,70 @@
+set argport 7670
+if {[lindex $argv 0] eq "-port"} {
+       set argport [lindex $argv 1]
+       set argv [lrange $argv 2 end]
+}
+set request [lindex $argv 0]
+set len [switch $request ping {expr -1} protocol {expr -2} version {expr -3} check {expr 1} default {expr $request}]
+set read_data {}
+
+proc get_port {} {
+       if {[regexp {^\d+$} $::argport]} {return $::argport}
+       set f [open $::argport r]
+       set r [read -nonewline $f]
+       close $f
+       return $r
+}
+
+proc get_data {socket} {
+       set read_data [read $socket]
+       if {$read_data eq ""} {
+               close $socket
+               handle_data
+       } else {
+               append ::read_data $read_data
+       }
+}
+
+proc handle_data {} {
+       global len read_data
+       if {$len > 0} {
+               if {$::request eq "check" && $read_data ne ""} {exit 0}
+               if {$read_data eq ""} {
+                       puts stderr "not ready"
+                       exit 1
+               }
+               binary scan $read_data H* data
+               set data [regsub -all ".{48}" [regsub -all ".." $data "& "] "&\n"]
+               if {[string index $data end] eq "\n"} {set data [string replace $data end end]}
+               puts $data
+       } else {
+               if {$len == -1 || $len == -3} {
+                       if {[string length $read_data] < 4} {error "Not enough data"}
+                       binary scan $read_data I rlen
+                       set read_data [string range $read_data 4 end]
+                       puts [encoding convertfrom utf-8 $read_data]
+                       if {[string length $read_data] != $rlen} {
+                               puts stderr "Real string length [string length $read_data] != claimed $rlen!"
+                               exit 2
+                       }
+               } elseif {$len == -2} {
+                       if {[string length $read_data] < 4} {error "Not enough data"}
+                       if {[string length $read_data] > 4} {error "Excess data"}
+                       binary scan $read_data I r
+                       puts $r
+               }
+       }
+       exit 0
+}
+
+set port [get_port]
+               
+if {[info exists errmsg] && $errmsg ne ""} {error $errmsg}
+if {$port eq ""} {error "Cannot find port number"}
+
+set s [socket localhost $port]
+fconfigure $s -encoding binary -buffering none -blocking 0
+fileevent $s readable [list get_data $s]
+puts -nonewline $s [binary format I $len]
+after 4000 {puts stderr "Timeout.  Read for now: '$read_data'"; exit 2}
+vwait forever