I am trying to implement the SRP protocol for a Server and Client app in Android. I checked that OpenSSL supports SRP protocol but how can I access OpenSSL APIs from the Android app? Is JNI the only way to access the OpenSSL C APIs? Are there any samples that I can refer how to build the OpenSSL for Android and to call the OpenSSL SRP APIs through JNI.
I am trying to implement the SRP protocol
I like SRP, too. Be sure to use Thomas Wu's specification, or version 6 of the IETF's specification.
OpenSSL supports SRP protocol but how can I access OpenSSL APIs from the Android app? Is JNI the only way to access the OpenSSL C APIs?
Yes.
You might also look to Bouncy Castle for a Java implementation.
Are there any samples that I can refer how to build the OpenSSL for Android...
See OpenSSL and Android on the OpenSSL wiki.
Android carries around a copy of OpenSSL, but I'm not sure of it includes SRP.
Are there any samples that I can refer ... to call the OpenSSL SRP APIs through JNI.
Not that I am aware. The closest you will find is the source code to s_client
, options like -srpuser <user>
, and data structures like srp_arg_st
, and functions like ssl_srp_verify_param_cb
and ssl_give_srp_client_pwd_cb
.
You can find the source code for s_client
at <openssl src dir>/apps/s_client.c
. Line 1365 looks interesting (from 1.0.2h):
# ifndef OPENSSL_NO_SRP
if (srp_arg.srplogin) {
if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
BIO_printf(bio_err, "Unable to set SRP username\n");
goto end;
}
srp_arg.msg = c_msg;
srp_arg.debug = c_debug;
SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
if (c_msg || c_debug || srp_arg.amp == 0)
SSL_CTX_set_srp_verify_param_callback(ctx,
ssl_srp_verify_param_cb);
}
# endif
And the srp_arg_st
from around line 475:
/* This is a context that we pass to all callbacks */
typedef struct srp_arg_st {
char *srppassin;
char *srplogin;
int msg; /* copy from c_msg */
int debug; /* copy from c_debug */
int amp; /* allow more groups */
int strength /* minimal size for N */ ;
} SRP_ARG;
Obviously, OpenSSL is native C and does not use JNI.
How to call OpenSSL SRP APIs ...?
At the highest levels, you need to do two or three things in C. Think of them as a supplement to a the standard TLS Client from the OpenSSL wiki. (I'm side stepping Android/JNI part).
First, you need to set the SSL_CTX_set_srp_*_callback
. The callbacks are how the library prompts your TLS client for information like username and password.
Second, you remove all non-SRP cipher suites. That means you do not use a cipher list like "HIGH:!aNULL:!MD5:!RC4"
.
Third, you use only SRP cipher suites. I'm not sure how the cipher list would look when using "HIGH:!aNULL:..."
. But you can hand pick the list of ciphers with:
$ openssl ciphers -v | grep SRP | grep -v DSS | cut -f 1 -d ' '
SRP-RSA-AES-256-CBC-SHA
SRP-AES-256-CBC-SHA
SRP-RSA-AES-128-CBC-SHA
SRP-AES-128-CBC-SHA
SRP-RSA-3DES-EDE-CBC-SHA
SRP-3DES-EDE-CBC-SHA
If you go to the openssl ciphers
man page, then you should be able to cross reference SRP-RSA-AES-256-CBC-SHA
with the name needed in the cipher list. Unfortunately, the SRP cipher suites are missing.
However, you can go to ICANN's TLS paramter registry and get the names:
So the string you would use for SSL_CTX_set_cipher_list
or SSL_set_cipher_list
:
static const char const PREFERRED_CIPHERS[] =
"TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA";