The public key exchange utilizes the WWW-Authenticate and Authorization HTTP headers, compliant with the access authentication framework specified in RFC-7235 section 2, and with their auth-scheme specifying SNWL-PK-AUTH.
A client must first invoke a challenge from the firewall by making a request to /api/sonicos/auth. Any method can be used for this, but it is suggested that a POST be used if the override parameter is to be set, or otherwise a HEAD request since no request data content is involved. This solicits a response as follows:
HTTP/1.0 401 Unauthorized
Server: SonicWall
WWW-Authenticate: SNWL-PK-AUTH type=RSA, key="..."
An exception for authentication is with CHAP authenticated via RADIUS, but it is not compatible with then doing session security.
The client will then need to resend the request to /api/sonicos/auth with an Authorization header as follows:
Authorization: SNWL-PK-AUTH user="admin", data="..."
The content of the key field in the challenge is the RSA public key, in ASN.1 type RSAPublicKey format (see RFC-3447 section A.1.1) and base64-encoded. This is what comes between the BEGIN and END markers in an RSA key in a .pem file, concatenated into a single line (with the BEGIN/END markers not included). For example with this RSA key:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdzKnaH+K2kfpHE2U7SDsbZMpd
Qu8vEYIdDlqrQx7BzQpfBGVy5CbTsJn+RiGPNYjtFAL+7Qux4wqc6aOnpWJoY/
BiBmoEKRumBOd2VJBr599yllfqQbXPwQEd9euWTlvaD7G+OhIWFMCnPRIOFkZxwc
1v+Aqq8FY/A/nMYPYwIDAQAB
-----END PUBLIC KEY-----
It would be the string “MIGfMA0G...YwIDAQAB”. The client can take this string and save it as a .pem file, enclosed in ----- BEGIN PUBLIC KEY----- / -----END PUBLIC KEY----- header/footer. That can then be used with openssl’s command-line RSA utility to encrypt a password using openssl by either of:
echo -n password | openssl rsautl -encrypt -pubin -inkey key-file.pem | base64 -w 0
echo -n password | openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:pkcs1 -pubin \ -inkey key-file.pem | base64 -w 0
Or if PKCS#1 v2.0 OAEP padding is selected (see below) by any one of:
echo -n password | openssl rsautl -encrypt -oaep -pubin -inkey key-file.pem | base64 -w 0
echo -n password | openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep -pubin \ -inkey key-file.pem | base64 -w 0
echo -n password | openssI pkeyutI -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt \ rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -pubin _inkey key-file.pem | base64 -w 0
The “openssl rsautl” is now deprecated and using “openssl pkeyutl” is preferred. In the case of OAEP, the first two forms above both use SHA-1 for the hashes in the OAEP padding, and the third form needs to be used for other hashing methods (such as SHA-256, as in the above example). Note that the latter is not supported in all SonicOS version.
The data field in the response holds the cipher data (encrypted password), base64-encoded (as output by the above commands).
The string could be piped through "fold -w 64" to break it into 64-character lines, as in the example above, but that is not necessary and a .pem file with a single long line between the header/footer lines works fine.
The following is an example bash script to send a public key authentication request to the firewall, extract the public key from the WWW-Authenticate challenge in the reply, use that to encrypt the password (with OAEP padding using SHA-256) and then send the response back to the firewall:
curl -k -i -s -X POST https://$ADDR/api/sonicos/auth | grep 'WWW-Authenticate: SNWL-PK-AUTH' \
| sed -e 's/^.*key="/-----BEGIN PUBLIC KEY-----\n/' \ -e 's/"/\n-----END PUBLIC KEY-----/' >pk.pem
CIPHER=$(echo -n "$PASSWORD" | openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep \
-pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -pubin -inkey pk.pem \
| base64 -w 0)
curl -k -i -s -H 'Authorization: SNWL-PK-AUTH user="'$USERNAME'", data="'$CIPHER'"' \
-X POST https://192.168.168.32/api/sonicos/auth