All source files are converted from cp1251 to utf-8.
--- /dev/null
+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
+}
--- /dev/null
+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
+}
--- /dev/null
+#!/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
--- /dev/null
+#-----------------------------------------------------------------------------
+# 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
+
--- /dev/null
+# 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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
+}
--- /dev/null
+Salted__»d°å\84½1\8e\82ÐÞo\1f\87tV\82ºÙ\8b
+"h;ó\a\ 6\17\9bhú\87
\ No newline at end of file
--- /dev/null
+\82ÐÞo\1f\87tV\82ºÙ\8b
+"h;ó\a\ 6\17\9bhú\87
\ No newline at end of file
--- /dev/null
+Salted__©\84\88¦\1c8\ 3>õ
+i¹«ÊS#Õ@ù\8dÃðgu\19\ 6\93ï$
\ No newline at end of file
--- /dev/null
+õ
+i¹«ÊS#Õ@ù\8dÃðgu\19\ 6\93ï$
\ No newline at end of file
--- /dev/null
+#!/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
+
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+Salted__h§®\9b\v5UÏ\eå,\13\9e~j³\88D±¤\ fug¼]\1e\17_'
\ No newline at end of file
--- /dev/null
+\eå,\13\9e~j³\88D±¤\ fug¼]\1e\17_'
\ No newline at end of file
--- /dev/null
+#
+# óÔÒÕËÔÕÒÁ ÆÁÊÌÁ
+# ÁÌÇÏÒÉÔÍ {
+# 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
+}
--- /dev/null
+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
+}
--- /dev/null
+#
+# óÔÒÕËÔÕÒÁ ÆÁÊÌÁ
+# ÁÌÇÏÒÉÔÍ {
+# 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
+}
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp3-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp36-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp36r2-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp36r3-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp36r4-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+gost2001:XA {
+ GOST2001-GOST89-GOST89 v-cp39-srv.vm.cryptocom.ru:443:iis
+}
+
--- /dev/null
+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
+}
--- /dev/null
+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
+}
--- /dev/null
+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
+}
--- /dev/null
+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
+}
--- /dev/null
+#!/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
--- /dev/null
+îîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîî\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
--- /dev/null
+012345678901234567890123456789012345678901234567890123456789012
\ No newline at end of file
--- /dev/null
+Ñå âåòðè, Ñòðèáîæè âíóöè, âåþòú ñ ìîðÿ ñòðåëàìè íà õðàáðûÿ ïëúêû Èãîðåâû
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+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
+
--- /dev/null
+#!/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]
+
+
+
+
--- /dev/null
+# -*- 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]
--- /dev/null
+# -*- 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 "Затираем контейнер без имени, даем с именем"
--- /dev/null
+#!/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
--- /dev/null
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGMMEAGCSqGSIb3DQEFDTAzMBsGCSqGSIb3DQEFDDAOBAi26UdKOFk+lgICCAAw
+FAYIKoZIhvcNAwcECGp4Z7XaD/vABEgfBlfcpKTWrDqMjzd2qra/uR5u+ogSKp3b
+CBLudt8opsMfrCrIUJk6NpTP1BVPa4nYqqKePWIY7p6S3pSxQWBkhsWmM7G3K/w=
+-----END ENCRYPTED PRIVATE KEY-----
--- /dev/null
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+N\98\11\f\97·¹<>%\r\93Öè]i\13m\86\88\a²ÛïV\8e¶\80«R¡-
\ No newline at end of file
--- /dev/null
+N\98\11\f\97·¹<>%\r\93Öè]i\13m\86\88\a²ÛïV\8e¶\80«R¡-
\ No newline at end of file
--- /dev/null
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
--- /dev/null
+\92Þðk<\13
+YÛTÇ\ 4ø\18\9d J\98û.g¨\ 2L\89\12@\9b\17µ~A
\ No newline at end of file
--- /dev/null
+#!/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
--- /dev/null
+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
+}
+
--- /dev/null
+proc oid {oid name types} {
+ puts "$oid $name GOST $name $oid"
+}
+
+source [lindex $argv 0]
--- /dev/null
+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
+}
--- /dev/null
+#!/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
--- /dev/null
+#!/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
+
--- /dev/null
+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
+
--- /dev/null
+#!/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 $?
--- /dev/null
+#
+# Расширение пакета 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
--- /dev/null
+#!/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
--- /dev/null
+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
--- /dev/null
+#!/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
--- /dev/null
+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]]
--- /dev/null
+Test data to encrypt
\ No newline at end of file
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQgNsz+6JQm0UYw
+I90/psShKQrktCj3ehyKe3G7dVuo+ySgODA2BggqhQMCCQMIATEqBChCIIzvjjnM
+EjW957oYXmI1tlNIIEMFy50EOPk4d/akd8k9UEUfJQ31
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwICHgEEIgQgvVb0e4AmOEIH
+jKiZj+29OgbFVwy+XHI48yKm8FJyjQygODA2BggqhQMCCQMIATEqBCh3mHOU3GbN
+IZuseCRP836vV2rBLOuQrVznWHPOb9VC0lB6eNOhY1GH
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICIwMGByqFAwICHgEEIgQgbIM6LxPe0Ave
+N+yRZBsb7jmIyZET+YiWpiN3T4sKGiOgODA2BggqhQMCCQMIATEqBCgftKdkhEXD
+VG50lrUkn9EbqriBTKRO8SK2Yu9VJfeVt9uDpYQ9dMu2
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIgQgSGtJ/s0X+5ld
+2wilev1VMOVYAiYPqxJeBCovJlnsB3agODA2BggqhQMCCQMIATEqBChquxeySqNx
+XJ+zRfoydNB3ZnI7WHvyCdevrpnUXi43QfJ7Bofldn7G
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MH8CAQAwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwICHgEEIgQgYAQQC17Sjt3F
+rg9m7PyzD9Pa2eAYTMr8ltX3IBOmukWgODA2BggqhQMCCQMIATEqBCgl8zuE43h4
+78dfpVXoV7bD85G2SIY1/d7o+bAr8AiQBumvzlnQr2ka
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwEGCCqFAwcBAQICBCIEIOTjkLas
+e0/SvSH/hFRSfBopnkP9a6mqCqP/zEf6WwFsoDgwNgYIKoUDAgkDCAExKgQoXql/
+cWe/7Tgh3csptrfiEgAaWgGS+VhzbJnZLvn9/STU1/46KWA+0A==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwIGCCqFAwcBAQICBCIEIO6zQc6w
+YqWlSTp4BBlVa3q+6w96tRtpWlp+LZjb5ShyoDgwNgYIKoUDAgkDCAExKgQotOvO
+EGwCt0ZcyZA+Lq3RwctxfJMIImyY48X/UilpdLTbfuxNTrAP7Q==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICIwMGCCqFAwcBAQICBCIEIAmU+PyI
+r/n63dlQoJhZu0NNJgay2KEFmtb2JvDsLDtzoDgwNgYIKoUDAgkDCAExKgQoTmXk
+7VWKAP0WNGF3y26CldydpwA1llejlnI3eZ0IaIq6In4K3SzWjw==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICJAAGCCqFAwcBAQICBCIEIAlnokn7
+Vw8a7IykYa4EYlv6zdit8QG5Fxs9wdWF/LuyoDgwNgYIKoUDAgkDCAExKgQopAxM
+Ymu/ufjc2DAxKwaMaeI1cQbNZGApKGrBgFr5/azc+wYpkV/tIg==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGCAgEAMB8GCCqFAwcBAQEBMBMGByqFAwICJAEGCCqFAwcBAQICBCIEIB7ziMjS
+yZxVTj9kzt5nyHoz0BVpvWkb8dAxo5SjV9KBoDgwNgYIKoUDAgkDCAExKgQoM1Rx
+tOEXmeWQll3cuet7UDp0YEmVid1AMvvdx3MD4LVthAmrIYKUCg==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGkAgEAMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAQYIKoUDBwEBAgMEQgRAdBFk
+9bJa60Rw9jvTNdtfZ3ImZuep2Klx5Fpap1bpBE4u/T4CI/R2nyjuWCBKPmbBHJO7
+4Z/BTUYYe04l0gWWZaA4MDYGCCqFAwIJAwgBMSoEKCHK4j/oPjNmh1w4eH6Zx1cQ
+kzLi1QCYb8u45IFtpBx0jF4O0etcYKo=
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIGkAgEAMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAgYIKoUDBwEBAgMEQgRAQ8Hd
+iGVmLyWQFF7lR2VnBIV/npcxJOTrsdhnSpNczZVT+ZWEvY66IQMsUPCVUcgZIYyp
+44E3v8kD6x0EuCmPcqA4MDYGCCqFAwIJAwgBMSoEKG0+06BM69y0EvoCeE4fP8jB
+XPhDcF9daMRu299ZaXv2H9o/OO+nC5A=
+-----END PRIVATE KEY-----
--- /dev/null
+-----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-----
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+@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
--- /dev/null
+#!/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
--- /dev/null
+@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
--- /dev/null
+@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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+-----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-----
+
--- /dev/null
+-----BEGIN CMS-----
+MIIBawYJKoZIhvcNAQcDoIIBXDCCAVgCAQIxgfehgfQCAQOgQjBAMDgxDTALBgNV
+BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp
+dAIEAYy6gqEiBCBvcfyuSF57y8vVyaw8Z0ch3wjC4lPKTrpVRXty4Rhk5DAXBgkq
+hQMHAQEHAQEwCgYIKoUDBwEBBgEwbjBsMEAwODENMAsGA1UEChMEVEsyNjEnMCUG
+A1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0AgQBjLqDBChPbi6B
+krXuLPexPAL2oUGCFWDGQHqINL5ExuMBG7/5XQRqriKARVa0MFkGCSqGSIb3DQEH
+ATAbBgkqhQMHAQEFAQEwDgQMdNdCKnYAAAAwqTEDgC9O2bYyTGQJ8WUQGq0zHwzX
+L0jFhWHTF1tcAxYmd9pX5i89UwIxhtYqyjX1QHju2g==
+-----END CMS-----
--- /dev/null
+-----BEGIN CMS-----
+MIIBlQYJKoZIhvcNAQcDoIIBhjCCAYICAQAxggEcMIIBGAIBADBAMDgxDTALBgNV
+BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp
+dAIEAYy6gzAXBgkqhQMHAQEHAgEwCgYIKoUDBwEBBgEEgbcwgbQEMFiMredFR3Mv
+3g2wqyVXRnrhYEBMNFaqqgBpHwPQh3bF98tt9HZPxRDCww0OPfxeuTBeMBcGCCqF
+AwcBAQEBMAsGCSqFAwcBAgEBAQNDAARAdFJ9ww+3ptvQiaQpizCldNYhl4DB1rl8
+Fx/2FIgnwssCbYRQ+UuRsTk9dfLLTGJG3JIEXKFxXWBgOrK965A5pAQg9f2/EHxG
+DfetwCe1a6uUDCWD+wp5dYOpfkry8YRDEJgwXQYJKoZIhvcNAQcBMB8GCSqFAwcB
+AQUCATASBBDUHNxmVclO/v3OaY9P7jxOgC+sD9CHGlEMRUpfGn6yfFDMExmYeby8
+LzdPJe1MkYV0qQgdC1zI3nQ7/4taf+4zRA==
+-----END CMS-----
--- /dev/null
+-----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-----
--- /dev/null
+-----BEGIN CMS-----
+MHEGCSqGSIb3DQEHBqBkMGICAQAwXQYJKoZIhvcNAQcBMB8GCSqFAwcBAQUCATAS
+BBBSwX+zyOEPPuGyfpsRG4AigC/P8ftTdQMStfIThVkE/vpJlwaHgGv83m2bsPay
+eyuqpoTeEMOaqGcO0MxHWsC9hQ==
+-----END CMS-----
--- /dev/null
+-----BEGIN CMS-----
+MIGIBgkqhkiG9w0BBwagezB5AgEAMFkGCSqGSIb3DQEHATAbBgkqhQMHAQEFAQIw
+DgQMuncOu3uYPbI30vFCgC9Nsws4R09yLp6jUtadncWUPZGmCGpPKnXGgNHvEmUA
+rgKJvu4FPHtLkHuLeQXZg6EZMBcGCSqFAwcBAAYBATEKBAjCbQoH632oGA==
+-----END CMS-----
--- /dev/null
+8F5EEF8814D228FB2BBC5612323730CFA33DB7263CC2C0A01A6C6953F33D61D5
--- /dev/null
+-----BEGIN CMS-----
+MH0GCSqGSIb3DQEHBaBwMG4CAQAwCgYIKoUDBwEBAgIwOwYJKoZIhvcNAQcBoC4E
+LMru7fLw7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEuBCD/
+esPQYsGkzxZV8uUMIAWt6SI8KtxBP8NyG8AGbJ8i/Q==
+-----END CMS-----
--- /dev/null
+-----BEGIN CMS-----
+MIGfBgkqhkiG9w0BBwWggZEwgY4CAQAwCgYIKoUDBwEBAgMwOwYJKoZIhvcNAQcB
+oC4ELMru7fLw7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEu
+BEDe4VUvcKSRvU7RFVhFjajXY+nJSUkUsoi3oOeJBnru4PErt8RusPrCJs614ciH
+CM+ehrC4a+M1Nbq77F/Wsa/v
+-----END CMS-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAZ+gAwIBAgIEAYy6gzAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD
+VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDBoMCEGCCqFAwcB
+AQEBMBUGCSqFAwcBAgEBAQYIKoUDBwEBAgIDQwAEQL8nghlzLGMKWHuWhNMPMN5u
+L6SkGqRiJ6qZxZb+4dPKbBT9LNVvNKtwUed+BeE5kfqOfolPgFusnL1rnO9yREOj
+gYUwgYIwYQYDVR0BBFowWIAUgNkM95n4Zk2TU4mOwJ5xLaenMRKhOjA4MQ0wCwYD
+VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i
+aXSCBAGMuoEwHQYDVR0OBBYEFLue+PUb9Oe+pziBU+MvNejjgrzFMAoGCCqFAwcB
+AQMCA0EAPP9Oad1/5jwokSjPpccsQ0xCdVYM+mGQ0IbpiZxQj8gnkt8sq4jR6Ya+
+I/BDkbZNDNE27TU1p3t5rE9NMEeViA==
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQgzre/jOVK
+ur0vHHsZfkIQhvXkUYzK8cOrSxG88h/cyA0=
+-----END PRIVATE KEY-----
--- /dev/null
+-----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-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MGgCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRA3HXF+fFK
+6VIJkvHOEhfbcu8ZFQ/bzSS/jLOlrVbAV4fx0YjznHwK387PilH91kv4sWIaWblO
+W8B/fAofmBUDpQ==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIB8DCCAZ2gAwIBAgIEAYy6gTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA4MQ0wCwYDVQQKEwRUSzI2MScwJQYD
+VQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMHAQEB
+ATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABEAaSoKcjw54UACci6svELNF0IYM
+RIW8urUsqamIpoG46XCqrVOuI6Q13N4dwcRsbZdqByf+GC2f5ZfO3baN5bTKo4GF
+MIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsGA1UE
+ChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0
+ggQBjLqBMB0GA1UdDgQWBBSA2Qz3mfhmTZNTiY7AnnEtp6cxEjAKBggqhQMHAQED
+AgNBAAgv248F4OeNCkhlzJWec0evHYnMBlSzk1lDm0F875B7CqMrKh2MtJHXenbj
+Gc2uRn2IwgmSf/LZDrYsKKqZSxk=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQgzre/jOVK
+ur0vHHsZfkIQhvXkUYzK8cOrSxG88h/cyA0=
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAaCgAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2
+MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw
+MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD
+VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMH
+AQEBATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABECWKQ0TYllqg4GmY3tBJiyz
+pXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZhuJaJfqZ6VbT
+o4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsG
+A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt
+Yml0ggQBjLqBMB0GA1UdDgQWBBTRnChHSWbQYwnJC62n2zu5Njd03zAKBggqhQMH
+AQEDAgNBAB41oijaXSEn58l78y2rhxY35/lKEq4XWZ70FtsNlVxWATyzgO5Wliwn
+t1O4GoZsxx8r6T/i7VG65UNmQlwdOKQ=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MEgCAQAwIQYIKoUDBwEBAQEwFQYJKoUDBwECAQEBBggqhQMHAQECAgQg6HfztrYQ
+Y/WOBUo0ORFCMsUWevdvbLfDx3iZRA6BIAs=
+-----END PRIVATE KEY-----
--- /dev/null
+-----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-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MGgCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRAEWkl+ebl
+sHWs86SNgRKqSxMOgGhbvR/uZ5/WWfdNG1axvUwVhpcXIxDZUmzQuNzqJBkseI7f
+5/JjXyTFRF1a+Q==
+-----END PRIVATE KEY-----
--- /dev/null
+-----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-----
--- /dev/null
+-----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-----
--- /dev/null
+# -*- 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
--- /dev/null
+#!/usr/bin/tclsh
+lappend auto_path [file dirname [info script]]
+package require ossltest
+cd $::test::dir
+start_tests "Тесты на команду dgst"
+end_tests
--- /dev/null
+#!/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
--- /dev/null
+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
+}
+
--- /dev/null
+#!/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
--- /dev/null
+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