NSS error -8023 using AWS SDK for PHP

Please note this fix should also work on Fedora, CentOS and Redhat linux distros if you are seeing the NSS error -8023 when using CURL and PHP.

At work we came up against this odd error message from Amazon Web Services(AWS) SDK for PHP when using the SDK in a forked process on the AWS built AMI:

PHP Fatal error:  Uncaught exception 'cURL_Exception' with message 'cURL resource: Resource id #50; cURL error: SSL connect error (cURL error code 35). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.' in /usr/share/pear/AWSSDKforPHP/lib/requestcore/requestcore.class.php:829

Stack trace:
#0 /usr/share/pear/AWSSDKforPHP/sdk.class.php(1035): RequestCore->send_request()
#1 /usr/share/pear/AWSSDKforPHP/services/swf.class.php(1305): CFRuntime->authenticate('TerminateWorkfl...', Array)
#2 ....php(189): AmazonSWF->terminate_workflow_execution(Array)
#3 ....php(83): daemon->checkSWFExecutions()
#4 ....php(350): daemon->run()
#5 {main}
  thrown in /usr/share/pear/AWSSDKforPHP/lib/requestcore/requestcore.class.php on line 829

Now, cURL error 35 means “A problem occurred somewhere in the SSL/TLS handshake. You really want the error buffer and read the message there as it pinpoints the problem slightly more. Could be certificates (file formats, paths, permissions), passwords, and others.” which is a bit vague and didn’t really help. After setting the CURLOPT_VERBOSE flag in the AWS SDK for PHP we were able to see the real error message:

NSS error -8023

As you may guess the next step was to look up what the NSS error code -8023 means(NSS and SSL Error Codes), which turned out to be: “A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.”

Unfortunately that error message isn’t very useful and whilst I may well be wrong sounds more like it may be an error in NSS than something we can easily solve in our code. The error wasn’t occurring on our local machines using the same version of PHP with a similar setup. This however was considerably more obvious than the above error message. Our local copies of CURL and in-turn php-curl were compiled against OpenSSL and not NSS.

To confirm the code on the AWS AMI was working other than the NSS error we temporarily disabled SSL/TLS for the connections to SWF and it worked as expected. We also tried (after re-enabling SSL) removing the process forking in php, and once again it worked fine. As mentioned in the PHP manual for pcntl-fork it can cause odd errors due to the way it takes an exact copy of the current process including all memory. So we tried creating a new instance of the AmazonSWF class within the code ran by the child process and calling the SWF API using that, no joy either. A quick Google on the problem turned up a few results with others having the same issue, the only suggestion found was to rebuild the NSS database, that didn’t solve the problem for us though.

The only thing left (without debugging NSS) was too recompile cURL against OpenSSL followed by recompiling php-curl (as luckily php-curl on the AWS AMI is compiled as a shared extension “.so” file) against the new copy of cURL. In case anyone else is unsure how to do this here is a brief how-to guide, it is quite simple though. You will need to install php-devel via yum if you don’t already have it to provide phpize.

Goto the cURL web site and get the URL for the latest copy of the cURL: http://curl.haxx.se/download.html then replacing the wget URL used here with the URL for the latest copy of cURL run:

yum install openssl-devel
wget http://curl.haxx.se/download/curl-7.27.0.tar.gz
tar -xf curl-7.27.0.tar.gz
cd curl-7.27.0
make install
cd ..
rm -Rf curl-7.27.0 curl-7.27.0.tar.gz

Now you can recompile php-curl, check the version of PHP you have to make sure you download the correct copy:

# Will tell you your php version
php -v
wget http://uk3.php.net/get/php-5.3.17.tar.gz/from/this/mirror
tar -xf php-5.3.17.tar.gz
cd php-5.3.17/ext/curl/
make install
cd ..
rm -Rf php-5.3.17 php-5.3.17.tar.gz

That should be it as all the defaults should be what you want. To confirm PHP is now using cURL compiled against OpenSSL you can always run the AWS SDK for PHP compatibility test script:

php /usr/share/pear/AWSSDKforPHP/_compatibility_test/sdk_compatibility_test_cli.php
  • This was a lifesaver! Thank you for posting!

  • Thanks! I generally avoid recompiling components of php like the plague (like sticking to yum), but in this case, I had no choice – my version simply wouldn’t work on Amazon Linux. Straight-forward in hindsight…worked like a charm!

  • MikeM

    Very grateful. here is an elasticbeanstalk extension to do the job (including some small amends i needed to make for current (Feb 2015) stock AWS Linux for PHP)

    mode: “000644”
    owner: root
    group: root
    content: |
    #!/usr/bin/env bash
    echo Defaults:root \!requiretty >> /etc/sudoers
    cd /home/ec2-user
    wget http://curl.haxx.se/download/curl-7.40.0.tar.gz
    tar -xf curl-7.40.0.tar.gz
    cd curl-7.40.0
    make install
    cd ..
    rm -Rf curl-7.40.0 curl-7.40.0.tar.gz
    wget –content-disposition http://uk3.php.net/get/php-5.5.17.tar.gz/from/this/mirror
    tar -xf php-5.5.17.tar.gz
    cd php-5.5.17/ext/curl/
    make install
    cd ..
    rm -Rf php-5.5.17 php-5.5.17.tar.gz
    sudo service httpd restart
    sudo initctl restart init-pulses
    echo Defaults:root requiretty >> /etc/sudoers
    command: sudo bash /home/ec2-user/recompile_curl.sh
    ignoreErrors: false

  • baw

    Thank you for this great post! We were running an older OS with CURL compiled against OpenSSL. We finally had to upgrade after several years and were very concerned about all our code breaking as we do heavy forking. Following your post we got rid of NSS and went back to OpenSSL and everything works great. Thank you again!