Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Api to load and verify the ssl certificate #118

Open
joicepj11 opened this issue Jan 22, 2019 · 4 comments
Open

New Api to load and verify the ssl certificate #118

joicepj11 opened this issue Jan 22, 2019 · 4 comments
Assignees

Comments

@joicepj11
Copy link

Hi Chris Conlon,
I used your library in android and in this API
WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, const char*);
your calling ProcessFile() method and trying to open file with file name but its failing, due to Android is not allowing to open file but if you can take file descriptor then FOPEN will work or use asset manager in NDK then it will be easily.

example:-
instead of fname, if you had file descriptor it will work in android or you use -DWOLFSSL_JNI flag and ask for AssetManager to process the file from assets directory it will also work.

file = XFOPEN(fname, "rb");
if (file == XBADFILE) return WOLFSSL_BAD_FILE;
if (XFSEEK(file, 0, XSEEK_END) != 0) {
XFCLOSE(file);
return WOLFSSL_BAD_FILE;
}
sz = XFTELL(file);
XREWIND(file);

@chandruscm
Copy link

chandruscm commented Feb 5, 2019

I'm facing the same issue, I'm not able to load the certificate from the Android assets folder through JNI.

However loading the certificate during run-time with an absolute path to the certificate in external storage works.

@joicepj11
Copy link
Author

Hi Chandramohan Sudar,

sample code to load the certificate file content

/* structure for file data content*/
struct SSLFileContent {
int sizeOfContentBuffer;
unsigned char *fileData;
};

/* code for reading file content*/

SSLFileContent getCertificateFileContentAndSize(){
assert(NULL != gJavaVM);
JNIEnv env1;
gJavaVM->AttachCurrentThread(&env1, NULL);
jclass cls = env1->GetObjectClass(jobj);
//getting asset manager instance from java code
methodAssetManager = env1->GetStaticMethodID(cls,"getAssetManager",()Landroid/content/res/AssetManager;");
jobject assetManager = env1->CallStaticObjectMethod(cls,methodAssetManager);
AAssetManager
mgr = AAssetManager_fromJava(env1, assetManager);
assert(NULL != mgr);

SSLFileContent fileContent;
AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
const char* filename = (const char*)NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
    if(strcmp(filename,"ca-cert.pem") == 0) {
        AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
        fileContent.sizeOfContentBuffer = static_cast<int>(AAsset_getLength(asset));
        fileContent.fileData = (unsigned char *) AAsset_getBuffer(asset);
        AAsset_close(asset);
        break;
    }
}
AAssetDir_close(assetDir);
return fileContent;

}

// and to load certificate content into wolfssl context object I added this method in ssl.c and definition in // ssl.h

/* CA PEM file for verification, may have multiple/chain certs to process /
int ProcessCertificateFromBufferContent(WOLFSSL_CTX
ctx, const unsigned char* buff,
long sz, int format, int type, WOLFSSL* ssl)
{
long used = 0;
int ret = 0;
int gotOne = 0;

WOLFSSL_MSG("Processing CA PEM file");
while (used < sz) {
    long consumed = 0;

    ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
                        &consumed, 0);

#ifdef WOLFSSL_WPAS
#ifdef HAVE_CRL
if (ret < 0) {
DerBuffer* der = NULL;
EncryptedInfo info;

        WOLFSSL_MSG("Trying a CRL");
        if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
                                                               NULL) == 0) {
            WOLFSSL_MSG("   Processed a CRL");
            wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
                                            der->length, WOLFSSL_FILETYPE_ASN1);
            FreeDer(&der);
            used += info.consumed;
            continue;
        }
    }

#endif
#endif
if (ret < 0) {
if (consumed > 0) { /* Made progress in file */
WOLFSSL_ERROR(ret);
WOLFSSL_MSG("CA Parse failed, with progress in file.");
WOLFSSL_MSG("Search for other certs in file");
}
else {
WOLFSSL_MSG("CA Parse failed, no progress in file.");
WOLFSSL_MSG("Do not continue search for other certs in file");
break;
}
}
else {
WOLFSSL_MSG(" Processed a CA");
gotOne = 1;
}
used += consumed;
}

if (gotOne) {
    WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
    return WOLFSSL_SUCCESS;
}
return ret;

}

// you can call for jni code like this

wolfSSL_Init();
if ((_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())) == nullptr) {
Log::error(_tag, "wolfSSL_CTX_new error.\n");
}
Log::info(_tag, "create wolf ssl context");
if (sslFileContent.fileData == nullptr) {
Log::error(_tag, "File Content is Null");
}

    if (sslFileContent.sizeOfContentBuffer == 0) {
        Log::error(_tag, "sizeOfContentBuffer of content buffer is zero");
    }

// this method was added in ssl.c file, above i have mentioned and this will work same as //wolfSSL_CTX_load_verify_locations() function
_ret = ProcessCertificateFromBufferContent(_ctx, sslFileContent.fileData,
sslFileContent.sizeOfContentBuffer,
SSL_FILETYPE_PEM,
CA_TYPE, nullptr);
if (_ret == SSL_FAILURE) {
Log::error(_tag, "Failed to load certificate");
}

@chandruscm
Copy link

chandruscm commented Feb 6, 2019

Thanks a lot @joicepj11 👍

Were you able to do it from Java? How do you point to the certificate file on the Android assets folder with this method?

wolfSSLContext.loadVerifyLocation(String file, String path);

I tried to pass the first String argument as mentioned in this SO post.
https://stackoverflow.com/questions/4820816/how-to-get-uri-from-an-asset-file

"file:///android_assets/ca-cert.pem"
"//android_assets/ca-cert.pem"

Also tried without extensions

"file:///android_assets/ca-cert"
"//android_assets/ca-cert"

Also tried to load the certificates from the raw resource directory as mentioned in the Android API documentation here

But none of them work. However, using an intent to pick the certificate from external storage and passing its absolute path as the first argument and keeping the second argument as null works!

@dgarske
Copy link
Contributor

dgarske commented Apr 29, 2019

Hi @chandruscm and @joicepj11,

I wanted to check in and see how things are going with this issue. Please let us know if you have any further issues.

Thanks,
David Garske, wolfSSL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants