The server is Liberty on z/OS. The server cert is self signed.
Command issued:
openssl s_client -CApath /home/ibmsys1 -showcerts -connect zito-zos.ddns.net:19181 < /dev/null
The following is returned:
CONNECTED(00000003)
depth=0 O = IBM, OU = C54WLP, CN = START1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = IBM, OU = C54WLP, CN = START1
verify error:num=21:unable to verify the first certificate
verify return:1
Certificate chain
0 s:O = IBM, OU = C54WLP, CN = START1
i:O = IBM, OU = C54WLP, CN = C54WLP Sample Certification Authority
The first in the chain is the server cert.
The second is the signing certauth.
In the folder given as CApath I placed "cacert.crt" that includes the certauth signing cert for
"CN = C54WLP Sample Certification Authority".
What is causing this error?
Related
I'm trying to decrypt an AES cipher generated by Ruby with the sjcl.js library.
I'm getting a "corrupt" error for an unknown reason……. I want to fix the problem.
For reference, when encryption and decryption were attempted in CBC mode, decryption was successful.
Ruby Code:
cipher = OpenSSL::Cipher.new('aes-256-gcm')
cipher.encrypt
iv = cipher.random_iv
cipher.key = Digest::SHA256.digest(password)
ciphertext = cipher.update(plaintext) + cipher.final
return Base64.strict_encode64(iv) + Base64.strict_encode64(ciphertext)
Javascript Code:
var iv = sjcl.codec.base64.toBits(IV_BASE64);
var ciphertext = sjcl.codec.base64.toBits(CIPHERTEXT_BASE64);
var key = sjcl.hash.sha256.hash(KEY_UTF8);
var decrypted = sjcl.mode.gcm.decrypt(new sjcl.cipher.aes(key), ciphertext, iv);
AES-GCM is an authenticated encryption algorithm. It automatically generates an authentication tag during encryption, which is used for authentication during decryption. This tag is not considered in the current Ruby code. It is 16 bytes by default, can be retrieved with cipher.auth_tag and must be added, e.g.:
ciphertext = cipher.update(plaintext) + cipher.final + cipher.auth_tag
Regarding nonce/IV, note that Base64 encoding should actually be done after concatenation (which, however, is not critical for a 12 bytes nonce/IV commonly used with GCM).
On the JavaScript side the separation of the nonce/IV is missing. Ciphertext and tag do not need to be separated because the sjcl processes the concatenation of both (ciphertext|tag):
const GCM_NONCE_LENGTH = 12 * 8
const GCM_TAG_LENGTH = 16 * 8
// Separate IV and ciptertext/tag combination
let ivCiphertextTagB64 = "2wLsVLuOJFX1pfwwjoLhQrW7f/86AefyZ7FwJEhJVIpU+iG2EITzushCpDRxgqK2cwVYvfNt7KFZ39obMMmIqhrDCIeifzs="
let ivCiphertextTag = sjcl.codec.base64.toBits(ivCiphertextTagB64)
let iv = sjcl.bitArray.bitSlice(ivCiphertextTag, 0, GCM_NONCE_LENGTH)
let ciphertextTag = sjcl.bitArray.bitSlice(ivCiphertextTag, GCM_NONCE_LENGTH)
// Derive key via SHA256
let key = sjcl.hash.sha256.hash("my password")
// Decrypt
let cipher = new sjcl.cipher.aes(key)
let plaintext = sjcl.mode.gcm.decrypt(cipher, ciphertextTag, iv, null, GCM_TAG_LENGTH)
//let plaintext = sjcl.mode.gcm.decrypt(cipher, ciphertextTag, iv) // works also; here the defaults for the AAD ([]) and the tag size (16 bytes) are applied
console.log(sjcl.codec.utf8String.fromBits(plaintext))
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sjcl/1.0.8/sjcl.min.js "></script>
The ciphertext used in the above code was generated with the Ruby code considering the authentication tag and is successfully decrypted.
Note that key derivation with a digest is insecure. Instead, a reliable key derivation function like PBKDF2 should be used.
I am trying to code a web service client in a RHEL 4 system (openssl 0.9.8b) (upgrade is not an option). I got the CA cert file to use, with two certificates, one is a self-signed root certificate. It works with "openssl s_client", but not from code. There I get error 7 (SSL certificate validation failed) from SSL_get_verify_result.
I made a test program, here are the basic parts:
SSL_library_init();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_load_verify_locations(ctx, "/etc/pki/mycert/cacert.pem", 0);
ssl = SSL_new(ctx);
sbio = BIO_new_socket(sock, BIO_NOCLOSE); /* The socket is already connected */
SSL_set_bio(ssl, sbio, sbio);
SSL_connect(ssl);
err = SSL_get_verify_result(ssl);
The connection works and the server sends its certificate; I have dumped it out with PEM_write_X509 and verified that it is accepted by "openssl verify".
I have used
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
to write out the steps of the verification in a callback function:
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
char buf[256];
X509 *err_cert;
int err, depth;
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
if (!preverify_ok)
printf("verify error:num=%d:%s:depth=%d:%s\n", err,
X509_verify_cert_error_string(err), depth, buf);
else
printf("Preverify OK, depth=%d:%s, err=%d\n", depth, buf, err);
...
The output of this is (some certificate data replaced with "..."):
Preverify OK, depth=2:/ST=GP/L=JHB/C ... QA Root CA 01, err=0
Preverify OK, depth=1:/C=ZA/DC=za/DC ... QA Issue CA 01, err=0
verify error:num=7:certificate signature failure:depth=0:/C=ZA ...
When running "openssl s_client" with this CA cert file as "-CAfile", the output starts with:
depth=2 /ST=GP/L=JHB/C ... QA Root CA 01
verify return:1
depth=1 /C=ZA/DC=za/DC ... QA Issue CA 01
verify return:1
depth=0 /C=ZA/ST ...
verify return:1
So what is the difference between what "openssl s_client" is doing, and what the code is doing?
I got it to work by adding "OpenSSL_add_all_algorithms()" to the code. It turned out that the algorithm used by the server cert was not found. The difference between the code and the openssl s_client command is obviously this call.
The code in the test program was taken from the Axis2/C source code, since my client is based on Axis2/C. So this call is missing there too.
Below is some output from curl --trace-time https://... which shows a 0.2 second delay in the middle of the TLS handshake. Any ideas on why this might be? I've tried with various cipher options and it persists. It also doesn't appear to be the result of something external (like a DNS lookup).
13:48:11.168371 * Connected to maas.its.iastate.edu (10.24.107.84) port 443 (#0)
13:48:11.168721 * SSLv3, TLS handshake, Client hello (1):
13:48:11.168761 } [data not shown]
13:48:11.183236 * SSLv3, TLS handshake, Server hello (2):
13:48:11.183348 { [data not shown]
13:48:11.183894 * SSLv3, TLS handshake, CERT (11):
13:48:11.183938 { [data not shown]
13:48:11.375841 * SSLv3, TLS handshake, Server finished (14):
13:48:11.375898 { [data not shown]
13:48:11.376106 * SSLv3, TLS handshake, Client key exchange (16):
13:48:11.376142 } [data not shown]
13:48:11.376203 * SSLv3, TLS change cipher, Client hello (1):
13:48:11.376240 } [data not shown]
13:48:11.376334 * SSLv3, TLS handshake, Finished (20):
13:48:11.376369 } [data not shown]
13:48:11.392527 * SSLv3, TLS change cipher, Client hello (1):
13:48:11.392585 { [data not shown]
13:48:11.392677 * SSLv3, TLS handshake, Finished (20):
13:48:11.392715 { [data not shown]
13:48:11.392788 * SSL connection using RC4-SHA
13:48:11.392825 * Server certificate: [cert details not shown]
13:48:11.393077 * SSL certificate verify ok.
13:48:11.393146 > GET /maas/example HTTP/1.1
13:48:11.409146 { [data not shown]
13:48:11.409438 * Closing connection #0
Run it under strace and use the -tt option:
http://linux.die.net/man/1/strace
Something like this:
strace -o /output/file -f -tt curl ...
The output will show you where the hang is - at least at the level of exactly what system call hangs.
This might be caused by a large certificate chain together with TCP slow start. See https://stackoverflow.com/a/29199493/3081018 for more details.
I wish to parse and display the contents of an Authenticode PKCS#7 signature as extracted from a Window PE binary's Security Directory.
I can use OpenSSL to do this on the command line with "openssl pkcs7 -text -in extracted_signature.pks -inform DER -print_certs", however I need to do this via C/C++ and the Windows API. I cannot use the OpenSSL library itself.
Using the CryptDecodeObjectEx API I can begin to decode the extracted signature:
CRYPT_CONTENT_INFO * content_info;
DWORD len;
CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
PKCS_CONTENT_INFO,
pointer_to_extracted_signature,
length_of_extracted_signature,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&content_info,
&len
);
The above call completes successfully and content_info->pszObjId will have an OID of "1.2.840.113549.1.7.2" (szOID_RSA_signedData) however I am unable to find the structures needed to continue decoding. The available OID's for CryptDecodeObjectEx are listed here.
Can anybody please advise how to decode an Authenticode PKCS#7 signature via the Windows API?
I have found the correct way to decode an Authenticode PKCS#7 signature is to use CryptQueryObject with the CERT_QUERY_OBJECT_BLOB and CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED flags set. Code snippit below for anybody who might need to do this.
CERT_BLOB cert_blob;
HCERTSTORE cert_store = NULL;
HCRYPTMSG cert_msg = NULL;
cert_blob.pbData = pointer_to_extracted_signature;
cert_blob.cbData = length_of_extracted_signature;
CryptQueryObject(
CERT_QUERY_OBJECT_BLOB,
&cert_blob,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
NULL,
NULL,
NULL,
&cert_store,
&cert_msg,
NULL
);
PCCERT_CONTEXT next_cert = NULL;
while( (next_cert = CertEnumCertificatesInStore( cert_store, next_cert ) ) != NULL )
{
// process next_cert...
}
I'm trying to connect to a webservice that requires SSL Client Authentication using ruby 2.1.2 but
When I use the same client certificate (client_cert.pem) on curl I've got the right response:
curl 'https://mywebservice.xxx.com' --cert client_cert.pem --cacert mycacert.crt
When I verbose curl I can see the handshaking going on like this:
* Hostname was NOT found in DNS cache
* Trying 192.168.0.10...
* Connected to mywebservice.xxx.com (192.168.0.10) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
* ...
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: mywebservice.xxx.com
> Accept: */*
>
* SSLv3, TLS handshake, Hello request (0):
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS handshake, CERT verify (15):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
< HTTP/1.1 200 OK
< Date: Thu, 17 Jul 2014 12:50:26 GMT
* Server Apache/2.2.16 (Debian) is not blacklisted
< Server: Apache/2.2.16 (Debian)
< Pragma: No-cache
< Cache-Control: no-cache
< Expires: Wed, 31 Dec 1969 21:00:00 BRT
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/xml;charset=utf-8
<
<?xml version='1.0' encoding='UTF-8'?> .....the full xml response
That's what I needed, but then I've tried the same on ruby:
#ws_test.rb
require 'net/http'
require 'uri'
require 'openssl'
uri = URI.parse 'https://mywebservice.xxx.com/'
http = Net::HTTP.new(uri.host, 443)
http.use_ssl = true
http.ssl_version = :TLSv1
cert = OpenSSL::X509::Certificate.new(File.read("client_cert.pem"))
http.cert = cert
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = OpenSSL::X509::Store.new
cacert = OpenSSL::X509::Certificate.new(File.read("mycacert.crt"))
http.cert_store.add_cert(cacert)
http.start do
http.request_get(uri.path) {|res|
print res.body
}
end
But on ruby I've got this problem:
/home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:920:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
from /home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:920:in `block in connect'
from /home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/timeout.rb:76:in `timeout'
from /home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:920:in `connect'
from /home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:863:in `do_start'
from /home/user/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:852:in `start'
I've tried to change the verify_mode:
http.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
# same error
and
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# a different error: " SSL_read: ssl handshake failure (OpenSSL::SSL::SSLError"
I've solved it using the gem rest_client...
This is what I did:
require 'rest_client'
RestClient::Resource.new(
'https://mywebservice.xxx.com/',
:ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("client_cert.crt")),
:ssl_client_key => OpenSSL::PKey::RSA.new(File.read("client_cert.key")),
:ssl_ca_file => "mycacert.crt",
:verify_ssl => OpenSSL::SSL::VERIFY_PEER
).get