# -*- mode: cperl; -*-
#
# This fragment is inserted into the Makefile.PL to ensure that signature verification works.
# It has been noted that old versions of OpenSSL will satisfy the Crypt::OpenSSL::xx modules,
# but not support verification.  The hex strings are CSRs and hash values that should verify.
# Hex is used for portability and readability.

{
    print STDERR ( "Checking crypto modules' operation with OpenSSL library ..." );
    my( @nover, @failtext );
    my $ok = eval {
        require Crypt::OpenSSL::DSA;

        my $key = Crypt::OpenSSL::DSA->read_pub_key_str( << '_KEY_' ) or die "Can't read DSA public key";
-----BEGIN PUBLIC KEY-----
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAOs6x6eSjwoque9hKIz94RwT6TLThTgD
2uslWeipGrydxIV3GVpHECbvJ3QfJOYNk6QlBvFs2L1a69v1GbW6o+ZHBITDw3kP
/JtWF/vThUXNB/9g2nhGODyEjwq0R6x+1dzTUTLYguAyafNpQzDUEpLZLkRyQp/6
DiUU7DXqlu4tAhUAsqEwY1v+Gduz5J2PXEuugmYSYBkCgYEA0qgvsy8wOqt8VUyR
CW0jPNPoeyyeICFypSBseiKKORlVBPz2JmdI6hohLO9rljK9wgEqdmh1yTM099rM
JP727RHBha9QKyNmN7/bP4+rHeK0vCa0XVu2FxuMFp7Kd5d7W0ucnKffQFLHcXvY
hduUNtCYKWWeiG3jUXPaU6FreNcDgYQAAoGAFVWpRu48Az2VrgwuYohcT9u9HlEb
xj9g9cYD8Jb/Hg9uaH3z+dus1ocuqnVgsaGRzBvlHYOwx8PYrvkebeuryShmpgOp
Zcs55fpyS9n7ML9XYFlSWnE4p1jOlHM6Am1XwZkGQ/0wCVcWpFNLNnlEIEPaic7F
Gs0wfthYSf4FK+I=
-----END PUBLIC KEY-----
_KEY_
        return $key->verify( pack( 'H*', 'a1d525953bc995b5c2568d5797b0e7525929bb7a46db1187c62d4ea3a040b746' ),
                             pack( 'H*', '302c021439b795be2af338ae34384fa8b235b67c2bbdeeb1021471ce864c3c1a' .
                                         'f74a8eb04a32dfeea17cc0ad2ac7' ) );
    };
    if( $@ || !$ok ) {
        push @nover, 'DSA';
        chomp $@;
        push @failtext, qq{Failed to verify DSA signature: $@};
    }
    $ok = eval {
        require Crypt::OpenSSL::RSA;

        my $key = Crypt::OpenSSL::RSA->new_public_key( << '_KEY_' ) or die "Can't read RSA public key";
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4EhMEu4ppW+3LSgp/fKG
hZsEmgB9kDASa90enSMZvji0pAsAQW3FSwADQLpYC7HFEeJR4aeB7CE5xS1B4WIm
9gfRxLMCekqVHq3IjpCxAN5WjyZ5AsaUOZ0TkrJ7en8x2EeV5R1oM+5GEyv8BJ+f
lizG9Q5RHxpWIn1H1+PWD4dW2RSo/PVECmflceQQb6bmyxy+bka5Sr7WLxG95LLP
ss8zBVhlTn8nzMgrKHCFF6MzajapMItWg8vz3MpJLNVjrjp00tM3QkpkR3HM6HBN
xH5n7P8jiVh6V+OiGXgTEUpYzs0mAHG/A8l6pLLQvw4fUTECArx97nm6nohKZSij
bwIDAQAB
-----END PUBLIC KEY-----
_KEY_
        $key->use_sha256_hash;
        $key->use_pkcs1_padding;

        return $key->verify( pack( 'H*', '308201b602010030818831133011060a0992268993f22c64011916036f'.
                                         '726731173015060a0992268993f22c64011916074f70656e53534c3115'.
                                         '3013060a0992268993f22c640119160575736572733123300b06035504'.
                                         '030c04746573743014060a0992268993f22c6401010c06313233343536'.
                                         '311c301a06092a864886f70d010901160d7465737440746573742e636f'.
                                         '6d30820122300d06092a864886f70d01010105000382010f003082010a'.
                                         '0282010100e0484c12ee29a56fb72d2829fdf286859b049a007d903012'.
                                         '6bdd1e9d2319be38b4a40b00416dc54b000340ba580bb1c511e251e1a7'.
                                         '81ec2139c52d41e16226f607d1c4b3027a4a951eadc88e90b100de568f'.
                                         '267902c694399d1392b27b7a7f31d84795e51d6833ee46132bfc049f9f'.
                                         '962cc6f50e511f1a56227d47d7e3d60f8756d914a8fcf5440a67e571e4'.
                                         '106fa6e6cb1cbe6e46b94abed62f11bde4b2cfb2cf330558654e7f27cc'.
                                         'c82b28708517a3336a36a9308b5683cbf3dcca492cd563ae3a74d2d337'.
                                         '424a644771cce8704dc47e67ecff2389587a57e3a2197813114a58cecd'.
                                         '260071bf03c97aa4b2d0bf0e1f51310202bc7dee79ba9e884a6528a36f'.
                                         '0203010001a000' ),
                             pack( 'H*', 'dc8ba14eade00b952cdaacf0f48986407f01802b3d2c626c0cea42f977'.
                                         'a39c3dbb58db01c1897fb72a3d46c811269e446c4c208f63030694216f'.
                                         '84ecca99163a60587e5bdf14075728e49e9b5e3992672021e694c1dcc2'.
                                         'a5f5ba4fb2c02de1453702ffe93ec2d9dbb3486f0a1e9cb75ee24e6f6a'.
                                         '23c4e57f8c611c5aec5de08e0a6b4ddff1d28f2ddcf5d61507f8dee490'.
                                         'deb185a20f2d52b29e43fc583d3b00b7ee9e7b54d2c4c828f7f7babf6d'.
                                         'd42d77dc2431029b61330e0b55a6dcc728f573af196fdebecdb4b78c48'.
                                         '3636e4c537fe36f69d86c5a7e024672a4504caa3a2be48e891ff4b83b4'.
                                         '815ea6972f54367466decce6be94c67aed04145392684726' ) );
    };
    if( $@ || !$ok ) {
        push @nover, 'RSA';
        chomp $@;
        push @failtext, qq{Failed to verify RSA signature: $@};
    }
    $ok = eval {
        require Crypt::PK::ECC;

        my $key = Crypt::PK::ECC->new( \<< '_KEY_' );
-----BEGIN PUBLIC KEY-----
MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABI0FB6fr9YoXkQ/isVsMRR6TvJSK
S6+3vxIE1gQ+feE5QjC++rnFEVzTzR4FmlRXiLseCDDuBjAMTz6NhxKPPdw=
-----END PUBLIC KEY-----
_KEY_
        return $key->verify_message( pack( 'H*', '30440220730d25ebe5f187c607577cc106d3141dc7f9082791'.
                                                 '4f2a6a11ebc9de6fdf1d26022042c02e4819f2c16c56181205'.
                                                 'c6c2176902f20cbfcfdc1fa82b30f79bd15d2172' ),
                                     pack( 'H*', '3081a80201003045310b300906035504061302415531133011'.
                                                 '06035504080c0a536f6d652d53746174653121301f06035504'.
                                                 '0a0c18496e7465726e6574205769646769747320507479204c'.
                                                 '7464305a301406072a8648ce3d020106092b24030302080101'.
                                                 '07034200048d0507a7ebf58a17910fe2b15b0c451e93bc948a'.
                                                 '4bafb7bf1204d6043e7de1394230befab9c5115cd3cd1e059a'.
                                                 '545788bb1e0830ee06300c4f3e8d87128f3ddca000' ),
                                     'SHA256' );
    };
    if( $@ || !$ok ) {
        push @nover, 'ECC';
        chomp $@;
        push @failtext, qq{Failed to verify ECC signature: $@};
    }

    if( @nover ) {
        # At least one signature failed to verify
        #
        # Do not allow Makefile creation.  Provide diagnostic.
        # Exit providing status for automated testing.

        my @removed;
        unlink( $_ ) && push @removed, $_ foreach( qw/Makefile Build/ );

        my $sslver;
        eval {
            local $SIG{__WARN__} = sub {};

            $sslver = qx/openssl version -a/;
            return unless( defined $sslver );

            require Text::Wrap;

            $sslver =~ s/^((?:compiler|options):[ ]+)([^\n]*)\n/
                       $1 . Text::Wrap::wrap( "", ' ' x 20, $2 ) . "\n"/gmsexi;
        };
        if( $? == 0 && defined $sslver && length $sslver ) {
            chomp $sslver;
            $sslver = sprintf( "    Installed version of OpenSSL:\n%s", $sslver );
            $sslver =~ s/\n/\n      /g;
            $sslver .= "\n";
        } else {
            $sslver = '';
        }

        # Include the following to make the test result 'na', omit for 'discard'
        #     OS unsupported
        # 'na' will produce reports not counted as FAIL; 'discard' won't report at all.

        my $diag = sprintf( qq(

    Unable to verify %s signatures.  You probably need to upgrade OpenSSL.
    You may also need to rebuild Crypt::PK::ECC, Crypt::OpenSSL::DSA and
    Crypt::OpenSSL::RSA.

    %s\n%s), join( ', ', @nover ), join( "\n    ", @failtext ), $sslver );

        $diag .=  sprintf( "\nDeleted old %s\n", join( ', ', @removed ) ) if( @removed );

        warn( $diag );
        exit 0;
    }
    print STDERR (" OK\n" );
}
# ####### End of SSL Test
