Android SSL Fails
Describe the issue
authResultCognito failed curlCode: 60, SSL peer certificate or SSH remote key was not OK; Details: SSL certificate problem: unable to get local issuer certificate
I'm at my wits end here. If I set clientConfig.caFile = "cacert.pem"; I get a 77 error I'm sure you're going to refer to the curl/openssl projects, but this is such a basic functionality of the aws SDK that it really should be documented here. I haven't found a functional solution anywhere. I've even tried replacing the curl/openssl libraries with the precompiled library from a specific android curl/openssl port.
Links
https://github.com/openssl/openssl/blob/master/NOTES-ANDROID.md
curl error 60 indicates that cert presented by the server could not be verified against trust store on your system. what are you trying to connect to? aws service or 3p? if its aws service, my guess would be that its due to outdated trust store on the device.
curl error 77 is due to curl not being able to open trust store file. you would need to provide a full code to do more debugging on this, but if you are just setting cafile to cacert.pem and cacert.pem is not in the same dir as executable i can see how curl would fail on that.
As best I can tell, its that the openssl version the SDK uses is 1.1.1 (current openssl is up to 3.5). In linux that links to the system openssl, so its clearly compatible with a recent version, but I cant figure out how to get it to use a recent openssl when compiling for android.
I'm running on the simulator, which can get to the AWS endpoint through the browser, so its certs are current. I dont think its a "device" issue.
I'm not so much worried about the 77 error (I'm literally trying anything I can think of), but the 60 error is out of the box (so to speak), which means the SDK does not work in android. I'm sure it does, but its not clear how to get it working.
version of openssl does not matter here. Each OS ships with a bundle of root certs that are maintained through OS specific mechanisms. When you establish connection to endpoint, client and underlying crypto implementation will verify the cert presented by server against those root certs on the system. error 60 indicates that that verification is failing, which typically is a sign of system root certs either being old or some root ca is missing.
Im not an expert on android, but check if your simulator version is recent enough. Also just running openssl directly to see if it can validate cert in the simulator might help narrow down the issue
On android, I think it does. This is the best clue I've found: https://github.com/openssl/openssl/issues/15154
Apologies, but I'm sort of figuring this out as I go. This could be a deadend, but it seems the certs are hashed differently in android (and may have changed at some point) and maybe the older version of openssl doesn't play nice with that?
Ah it gets more complicated then if openssl cannot parse the format that android provides certs in. Dont think we can recommend anything other than overriding the certs to a format that openssl does understand
Shouldn't it just be able to use the system certs. It seems like openssl has solved that problem in more recent versions, but the aws-sdk-cpp build tools insist on using an old version by default.
I've tried to get the SDK to build with external libraries, but that seems impossible on android (the build system is very opaque, so its entirely possible I haven't set something simple). A documented build command that would produce a linkage with a modern openssl (and curl)... for android... would be super helpful.
Overriding to use different certs led me down that 77 error. There's a whole other can of works with android and its horrible file system security.
SDK is not doing anything too fancy with libcrypto, it links against whatever cmake finds, so typical cmake flags for openssl should work. ex.
-DOPENSSL_ROOT_DIR=/path/to/openssl
-DOPENSSL_LIBRARIES=/path/to/openssl/lib
-DOPENSSL_INCLUDE_DIR=/path/to/openssl/include \
I had that... Actually specifying the library file itself. This time I looked over the cmake output and got this:
...
[370/372] Building C object crypto/fipsmodule/CMakeFiles/fipsmodule.dir/bcm.c.o
[371/372] Linking C static library crypto/libcrypto.a
[371/372] Install the project...
-- Install configuration: "Release"
-- Installing: /home/spanky/GitRepos/aws-sdk-cpp/build_android/deps/AWSLC/install/include/openssl
-- Installing: /home/spanky/GitRepos/aws-sdk-cpp/build_android/deps/AWSLC/install/include/openssl/bio.h
...
Looking at /home/spanky/GitRepos/aws-sdk-cpp/build_android/deps/AWSLC/install/include/openssl/opensslv.h, its 0x1010107f, which is old
It appears to be finding my curl, so at least I'm doing "something" right
-- Found CURL: /home/spanky/GitRepos/curl/android_libcurl_x86_64/lib/libcurl.a (found version "8.14.0-DEV")
likewise with my libcrypto.a
But I dont see it finding my openssl. Its like its not even looking for it.
I think what I'm looking for is someone to confirm that this even works on android. I'm likely screwing something up, but I've tried this so many different ways that I feel like its just not as simple as the wrong cmake flags. Again, I can get it to compile and run on android, but it just doesn't do the one most basic thing a web based API SDK is supposed to (actually connect via https).
For what its worth, I've got it working on linux, mac, ios, and windows. Why android is being such a pain is a mystery.
AWSLC is aws fork of boringssl, which is in turn fork of openssl around 1.1.1.
How are you building for android explicitly? Looks like we have a custom script for android builds https://github.com/aws/aws-sdk-cpp/tree/main/tools/android-build that already does some packaging, but im not familiar with it at all. @sbiscigl who might know more about it
Basically this:
cmake .. \
-GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=Android \
-DTARGET_ARCH=ANDROID \
-DNDK_DIR="${ANDROID_NDK}" \
-DANDROID_NATIVE_API_LEVEL=21 \
-DANDROID_ABI=${MY_ABI} \
-DANDROID_BUILD_ZLIB=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DENABLE_TESTING=OFF \
-DAUTORUN_UNIT_TESTS=OFF \
-DBUILD_ONLY="s3;dynamodb;cognito-identity;cognito-idp" \
-DCMAKE_INSTALL_PREFIX="~/GitRepos/aws-sdk-cpp/libaws_android/${MY_ABI}"
cmake --build . --config=Release
cmake --install . --config=Release
Can anyone confirm that this actually works on android? The above gets me to compile and run the SDK in my app, but its practically useless without the ability to make a connection to the server.
note that the error you are seeing is coming from curl and the command you are using will just build sdk, which will pick up whatever curl you have on the path. libcrypto that sdk links in this case might not be relevant (it gets tricky when you include multiple different libs that all compiled against different versions of libcrypto, which is why we recommend to use same libcrypto for sdk and for curl, etc...).
Where is curl coming from? is it a specific android version?
The android tools are pulling that in and compiling it. It compiles curl openssl, and zlib, unless explicitly turned off (although at least with openssl, it insists on building it from 1.1.1g)
Here's the cmake output from the above command:
[700/700] Linking C executable tests/server/fake_ntlm
[15/16] Performing install step for 'CURL'
[0/1] Install the project...
-- Install configuration: "Release"
-- Installing: /home/spanky/GitRepos/aws-sdk-cpp/libaws_android/x86_64/external-install/curl/bin/curl-config
-- Installing: /home/spanky/GitRepos/aws-sdk-cpp/libaws_android/x86_64/external-install/curl/lib/pkgconfig/libcurl.pc
-- Installing: /home/spanky/GitRepos/aws-sdk-cpp/libaws_android/x86_64/external-install/curl/include/curl/curlbuild.h
Its not entirely obvious that its actually compiling it, but it drops the curl repo in the build folder. Also, my system curl is 8.11.0, and the one running on the android simulator (linked in from the external-install folder) is 7.52.1-DEV. See the CMakeLists.txt file in the tools/android_build folder you referenced. The tools are definitely building it.
Again, I'm still trying to determine if even is a library issue. Can someone please, please, please confirm that this sdk works on android. Was this ever actually tested as functional (because it does appear to run fine until you try and actually interact with the server)
Any updates?
Arriving a little late at this discussion so trying to figure out what is going on here.
Can someone please, please, please confirm that this sdk works on android
yes it does work on android we have a CI step that runs nightly to check that we dont break compilation specifically with the arguments
cmake -GNinja -DCMAKE_BUILD_TYPE="Debug"
-DNDK_DIR="/android-ndk-r26d"
-DTARGET_ARCH=ANDROID
-DANDROID_NATIVE_API_LEVEL=26
-DANDROID_ABI=arm64-v8a
-DANDROID_BUILD_OPENSSL=ON
-DANDROID_BUILD_ZLIB=OFF
-DANDROID_BUILD_CURL=ON
I think the important thing here to note is the ANDROID_BUILD_* arguments which do not use the build systems libcrypto, they fetch and build the dependencies alongside the SDK. those are pegged at specific versions. If you want to use your own versions of those set all of the ANDROID_BUILD_* variables to OFF and place your dependencies in the CMAKE_PREFIX_PATH. if you want to fetch and build those dependencies at build time, set them to on.
So i guess the question is then, do you have you own depencies you want to be bringing and are you placing them in the CMAKE_PREFIX_PATH, or do you want to fetch and build the dependencies against the the android SDK when you build it.
Then at application build/runtime, are you expecting the SDK as a dynamic or static lib? its dependencies as dynamic ro static lib?
@sbiscigl thanks for the response. To clarify, it does compile and “run” but fails to connect to the AWS service. Specifically the curl error 60.
I’ve compiled and ran a separate libcurl to verify it’s not a system, device, or other configuration issue (I can do simple https calls from my compiled libcurl, but not from the one that is compiled from the SDK). I’ve tried turning off the SDK builds, but somewhere in there it insists on using its own. I think its in one of the submodules, but I haven’t dug deeper into it. I believe that was only for libcurl. The other libraries (crypto/ssl) linked as expected through the cmake commands.
Again, can someone please confirm that the SDK does more than just compile and run? Can it actually make a secure API call to the AWS backend? A lot of these issues are user error (and I’m more than willing to admit if it is), but I’ve been chasing my tail on this for a while. I can get libcurl to work, just not with the SDK (neither its own, nor my functional external libcurl)
@sbiscigl I also just tried this on my macbook (all the previous stuff was on my linux machine). Same curl error 60.
Here's the exact build command. I had some linker errors on <30 API on some generic libc sort of symbols. I didn't dig into that, but upping the API_LEVEL solved that issue (not the bigger curl error 60 issue)
export ANDROID_NDK=/Users/spanky/Library/Android/sdk/ndk/26.1.10909125
export MY_ABI=arm64-v8a
cmake .. \
-GNinja \
-DCMAKE_BUILD_TYPE="Release" \
-DNDK_DIR="${ANDROID_NDK}" \
-DTARGET_ARCH=ANDROID \
-DANDROID_NATIVE_API_LEVEL=34 \
-DANDROID_ABI=${MY_ABI} \
-DANDROID_BUILD_OPENSSL=ON \
-DANDROID_BUILD_ZLIB=OFF \
-DANDROID_BUILD_CURL=ON \
-DBUILD_DOCS=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DENABLE_TESTING=OFF \
-DCMAKE_INSTALL_PREFIX="/Users/spanky/GitRepos/aws-sdk-cpp/dist/android/${MY_ABI}" \
-DBUILD_ONLY="s3;dynamodb;cognito-identity;cognito-idp"
Clarifying --- the linker errors were actually on the minsdk on the module gradle in the actual android project... I dont think I needed 34 in the above build command, but apparently I changed this one first.
Again, can someone please confirm that the SDK does more than just compile and run?
yes, we have a script here that we use to build and test it. This script slipped out of nightly CI at some point in the past. i've currently been trying to get it working but am getting pulled in a few different directions. Currently trying to get reproduction of it running, bare with me while i get one together
Any updates on this? It appears the same issue impacts the ios build (curl failing on API requests with error 60 on an out-of-the-box build of aws-cpp-sdk). With ios though, it utilizes the external curl/ssl libraries when provided.
Just checking in on this. I cant be the only one using android and ios with this library... can I?