[Android] Improve assumption handling in Cryptography.Native.Android (#52449)
authorMarek Habersack <grendel@twistedcode.net>
Wed, 12 May 2021 09:53:31 +0000 (11:53 +0200)
committerGitHub <noreply@github.com>
Wed, 12 May 2021 09:53:31 +0000 (05:53 -0400)
20 files changed:
src/libraries/Native/Unix/Common/pal_compiler.h
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_bignum.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecc_import_export.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecdh.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecdsa.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_eckey.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_err.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_evp.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_hmac.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_misc.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_rsa.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_signature.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509chain.c
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509store.c

index c53dc3996fedae012c7416252be793ccde2dea86..8a94cb64cccdd989c766c0b34db8ce307d8f4080 100644 (file)
@@ -3,6 +3,15 @@
 
 #pragma once
 
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#if defined(TARGET_ANDROID)
+#include <stdlib.h>
+#include <android/log.h>
+#endif
+
 #ifndef __has_extension
 #define __has_extension(...) 0
 #endif
 #define c_static_assert(e) c_static_assert_msg(e, "")
 #endif
 
+#if defined(TARGET_ANDROID)
+static inline void
+do_abort_unless (bool condition, const char* fmt, ...)
+{
+    if (condition) {
+        return;
+    }
+
+    va_list ap;
+
+    va_start (ap, fmt);
+    __android_log_vprint (ANDROID_LOG_FATAL, "DOTNET", fmt, ap);
+    va_end (ap);
+
+    abort ();
+}
+#endif
+
+#define abort_unless(_condition_, _fmt_, ...) do_abort_unless (_condition_, "%s:%d (%s): " _fmt_, __FILE__, __LINE__, __FUNCTION__, ## __VA_ARGS__)
+#define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != NULL, "Parameter '%s' must be a valid pointer", #_ptr_)
+#define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_)
+
 #ifndef PALEXPORT
 #ifdef TARGET_UNIX
 #define PALEXPORT __attribute__ ((__visibility__ ("default")))
index 6280b4fd5c0073d6537dc364739093140f3e063c..70dcc99a86abbec8163b8b8364a39b80c40842c7 100644 (file)
@@ -5,6 +5,12 @@
 
 int32_t AndroidCryptoNative_BigNumToBinary(jobject bignum, uint8_t* output)
 {
+    // JNI requires object passed to `Call*Method` to be not NULL
+    abort_if_invalid_pointer_argument (bignum);
+
+    // JNI requires `output` to be not NULL when passed to `{Get,Set}ByteArrayRegion`
+    abort_if_invalid_pointer_argument (output);
+
     // bigNum.toByteArray()
     JNIEnv* env = GetJNIEnv();
     jbyteArray bytes = (jbyteArray)(*env)->CallObjectMethod(env, bignum, g_toByteArrayMethod);
@@ -27,6 +33,9 @@ int32_t AndroidCryptoNative_BigNumToBinary(jobject bignum, uint8_t* output)
 
 int32_t AndroidCryptoNative_GetBigNumBytes(jobject bignum)
 {
+    // JNI requires object passed to `Call*Method` to be not NULL
+    abort_if_invalid_pointer_argument (bignum);
+
     // bigNum.bitlength();
     // round up to the nearest byte
     JNIEnv* env = GetJNIEnv();
@@ -36,6 +45,9 @@ int32_t AndroidCryptoNative_GetBigNumBytes(jobject bignum)
 
 jobject AndroidCryptoNative_BigNumFromBinary(uint8_t* bytes, int32_t len)
 {
+    // JNI requires `bytes` to be not NULL when passed to `{Get,Set}ByteArrayRegion`
+    abort_if_invalid_pointer_argument (bytes);
+
     // return new BigInteger(bytes)
     JNIEnv* env = GetJNIEnv();
     jbyteArray buffArray = (*env)->NewByteArray(env, len);
@@ -47,6 +59,9 @@ jobject AndroidCryptoNative_BigNumFromBinary(uint8_t* bytes, int32_t len)
 
 int32_t AndroidCryptoNative_GetBigNumBytesIncludingPaddingByteForSign(jobject bignum)
 {
+    // JNI requires object passed to `Call*Method` to be not NULL
+    abort_if_invalid_pointer_argument (bignum);
+
     // Use the array here to get the leading zero byte if it exists.
     // bigNum.toByteArray().length();
     JNIEnv* env = GetJNIEnv();
index 99b2fd59131cd328d68fb2f9eb4e9cb63f5cbb78..6a4a4c63135a8d48a18909f9255c333c41c1115f 100644 (file)
@@ -69,6 +69,8 @@ static jobject GetAlgorithmName(JNIEnv* env, CipherInfo* type)
 
 CipherCtx* AndroidCryptoNative_CipherCreatePartial(CipherInfo* type)
 {
+    abort_if_invalid_pointer_argument (type);
+
     JNIEnv* env = GetJNIEnv();
     jobject algName = GetAlgorithmName(env, type);
     if (!algName)
@@ -158,7 +160,7 @@ int32_t AndroidCryptoNative_CipherSetKeyAndIV(CipherCtx* ctx, uint8_t* key, uint
     // Cipher: 2 for Decrypt, 1 for Encrypt, N/A
     if (enc != -1)
     {
-        assert(enc == 0 || enc == 1);
+        abort_unless(enc == 0 || enc == 1, "The 'enc' parameter must be either 1 or 0");
         ctx->encMode = enc == 0 ? CIPHER_DECRYPT_MODE : CIPHER_ENCRYPT_MODE;
     }
 
@@ -211,6 +213,8 @@ int32_t AndroidCryptoNative_CipherUpdateAAD(CipherCtx* ctx, uint8_t* in, int32_t
     if (!ctx)
         return FAIL;
 
+    abort_if_invalid_pointer_argument(in);
+
     JNIEnv* env = GetJNIEnv();
     jbyteArray inDataBytes = (*env)->NewByteArray(env, inl);
     (*env)->SetByteArrayRegion(env, inDataBytes, 0, inl, (jbyte*)in);
@@ -228,6 +232,9 @@ int32_t AndroidCryptoNative_CipherUpdate(CipherCtx* ctx, uint8_t* outm, int32_t*
         // it means caller wants us to record "inl" but we don't need it.
         return SUCCESS;
 
+    abort_if_invalid_pointer_argument(outl);
+    abort_if_invalid_pointer_argument(in);
+
     JNIEnv* env = GetJNIEnv();
     jbyteArray inDataBytes = (*env)->NewByteArray(env, inl);
     (*env)->SetByteArrayRegion(env, inDataBytes, 0, inl, (jbyte*)in);
@@ -252,6 +259,9 @@ int32_t AndroidCryptoNative_CipherFinalEx(CipherCtx* ctx, uint8_t* outm, int32_t
     if (!ctx)
         return FAIL;
 
+    abort_if_invalid_pointer_argument(outm);
+    abort_if_invalid_pointer_argument(outl);
+
     JNIEnv* env = GetJNIEnv();
 
     *outl = 0;
index eb9190de8faccd1f6190aefcd81baadeb39862e3..f45e185be1576321150eacb8355bb5f4dda40afd 100644 (file)
@@ -9,7 +9,7 @@
 
 int32_t AndroidCryptoNative_DsaGenerateKey(jobject* dsa, int32_t bits)
 {
-    assert(dsa);
+    abort_if_invalid_pointer_argument (dsa);
 
     // KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
     // kpg.initialize(bits);
@@ -42,7 +42,7 @@ int32_t AndroidCryptoNative_DsaGenerateKey(jobject* dsa, int32_t bits)
 
 static jobject GetQParameter(JNIEnv* env, jobject dsa)
 {
-    assert(dsa);
+    abort_if_invalid_pointer_argument (dsa);
 
     jobject ret = NULL;
 
@@ -64,7 +64,7 @@ cleanup:
 
 int32_t AndroidCryptoNative_DsaSizeSignature(jobject dsa)
 {
-    assert(dsa);
+    abort_if_invalid_pointer_argument (dsa);
 
     // The maximum size of a signature for the provided key is 2* bitlength of Q + extra bytes for the DER
     // encoding. The DER encoding is as follows (with R and S being the components of the signature and all lengths
@@ -89,7 +89,7 @@ int32_t AndroidCryptoNative_DsaSizeSignature(jobject dsa)
 
 int32_t AndroidCryptoNative_DsaSizeP(jobject dsa)
 {
-    assert(dsa);
+    abort_if_invalid_pointer_argument (dsa);
 
     JNIEnv* env = GetJNIEnv();
     INIT_LOCALS(loc, algName, keyFactory, publicKey, publicKeySpec, p);
@@ -142,9 +142,9 @@ int32_t AndroidCryptoNative_DsaSign(
     uint8_t* refsignature,
     int32_t* outSignatureLength)
 {
-    assert(hash);
-    assert(refsignature);
-    assert(dsa);
+    abort_if_invalid_pointer_argument (hash);
+    abort_if_invalid_pointer_argument (refsignature);
+    abort_if_invalid_pointer_argument (dsa);
     if (!outSignatureLength)
     {
         return FAIL;
@@ -178,9 +178,9 @@ int32_t AndroidCryptoNative_DsaVerify(
     uint8_t* signature,
     int32_t signatureLength)
 {
-    assert(hash);
-    assert(signature);
-    assert(dsa);
+    abort_if_invalid_pointer_argument (hash);
+    abort_if_invalid_pointer_argument (signature);
+    abort_if_invalid_pointer_argument (dsa);
     JNIEnv* env = GetJNIEnv();
 
     jobject signatureObject = GetDsaSignatureObject(env);
@@ -204,17 +204,17 @@ int32_t AndroidCryptoNative_GetDsaParameters(
     jobject* y, int32_t* yLength,
     jobject* x, int32_t* xLength)
 {
-    assert(dsa);
-    assert(p);
-    assert(q);
-    assert(g);
-    assert(y);
-    assert(x);
-    assert(pLength);
-    assert(qLength);
-    assert(gLength);
-    assert(yLength);
-    assert(xLength);
+    abort_if_invalid_pointer_argument (dsa);
+    abort_if_invalid_pointer_argument (p);
+    abort_if_invalid_pointer_argument (q);
+    abort_if_invalid_pointer_argument (g);
+    abort_if_invalid_pointer_argument (y);
+    abort_if_invalid_pointer_argument (x);
+    abort_if_invalid_pointer_argument (pLength);
+    abort_if_invalid_pointer_argument (qLength);
+    abort_if_invalid_pointer_argument (gLength);
+    abort_if_invalid_pointer_argument (yLength);
+    abort_if_invalid_pointer_argument (xLength);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -267,11 +267,7 @@ int32_t AndroidCryptoNative_DsaKeyCreateByExplicitParameters(
     uint8_t* x,
     int32_t xLength)
 {
-    if (!outDsa)
-    {
-        assert(false);
-        return 0;
-    }
+    abort_if_invalid_pointer_argument (outDsa);
 
     JNIEnv* env = GetJNIEnv();
 
index 924e6be61a9ea9996162d708c121966050cfea10..9b831a0a32d45d24d03774c591161d0599c1ae29 100644 (file)
@@ -17,12 +17,12 @@ int32_t AndroidCryptoNative_GetECKeyParameters(const EC_KEY* key,
                                         jobject* d,
                                         int32_t* cbD)
 {
-    assert(qx != NULL);
-    assert(cbQx != NULL);
-    assert(qy != NULL);
-    assert(cbQy != NULL);
-    assert(d != NULL);
-    assert(cbD != NULL);
+    abort_if_invalid_pointer_argument (qx);
+    abort_if_invalid_pointer_argument (cbQx);
+    abort_if_invalid_pointer_argument (qy);
+    abort_if_invalid_pointer_argument (cbQy);
+    abort_if_invalid_pointer_argument (d);
+    abort_if_invalid_pointer_argument (cbD);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -115,22 +115,22 @@ int32_t AndroidCryptoNative_GetECCurveParameters(const EC_KEY* key,
                                           jobject* seed,
                                           int32_t* cbSeed)
 {
-    assert(p != NULL);
-    assert(cbP != NULL);
-    assert(a != NULL);
-    assert(cbA != NULL);
-    assert(b != NULL);
-    assert(cbB != NULL);
-    assert(gx != NULL);
-    assert(cbGx != NULL);
-    assert(gy != NULL);
-    assert(cbGy != NULL);
-    assert(order != NULL);
-    assert(cbOrder != NULL);
-    assert(cofactor != NULL);
-    assert(cbCofactor != NULL);
-    assert(seed != NULL);
-    assert(cbSeed != NULL);
+    abort_if_invalid_pointer_argument (p);
+    abort_if_invalid_pointer_argument (cbP);
+    abort_if_invalid_pointer_argument (a);
+    abort_if_invalid_pointer_argument (cbA);
+    abort_if_invalid_pointer_argument (b);
+    abort_if_invalid_pointer_argument (cbB);
+    abort_if_invalid_pointer_argument (gx);
+    abort_if_invalid_pointer_argument (cbGx);
+    abort_if_invalid_pointer_argument (gy);
+    abort_if_invalid_pointer_argument (cbGy);
+    abort_if_invalid_pointer_argument (order);
+    abort_if_invalid_pointer_argument (cbOrder);
+    abort_if_invalid_pointer_argument (cofactor);
+    abort_if_invalid_pointer_argument (cbCofactor);
+    abort_if_invalid_pointer_argument (seed);
+    abort_if_invalid_pointer_argument (cbSeed);
 
     // Get the public key parameters first in case any of its 'out' parameters are not initialized
     int32_t rc = AndroidCryptoNative_GetECKeyParameters(key, includePrivate, qx, cbQx, qy, cbQy, d, cbD);
@@ -159,7 +159,7 @@ int32_t AndroidCryptoNative_GetECCurveParameters(const EC_KEY* key,
     }
     else
     {
-        assert((*env)->IsInstanceOf(env, loc[field], g_ECFieldFpClass));
+        abort_unless((*env)->IsInstanceOf(env, loc[field], g_ECFieldFpClass), "Must be an instance of java.security.spec.ECFieldFp");
         *curveType = PrimeShortWeierstrass;
         // Get the prime p
         bn[P] = (*env)->CallObjectMethod(env, loc[field], g_ECFieldFpGetP);
@@ -341,11 +341,7 @@ int32_t AndroidCryptoNative_EcKeyCreateByKeyParameters(EC_KEY** key,
                                                 uint8_t* d,
                                                 int32_t dLength)
 {
-    if (!key || !oid)
-    {
-        assert(false);
-        return 0;
-    }
+    abort_if_invalid_pointer_argument (key);
 
     *key = NULL;
 
@@ -422,12 +418,15 @@ EC_KEY* AndroidCryptoNative_EcKeyCreateByExplicitParameters(ECCurveType curveTyp
                                                      uint8_t* seed,
                                                      int32_t seedLength)
 {
-    if (!p || !a || !b || !gx || !gy || !order || !cofactor)
-    {
-        // qx, qy, d and seed are optional
-        assert(false);
-        return 0;
-    }
+    abort_if_invalid_pointer_argument (p);
+    abort_if_invalid_pointer_argument (a);
+    abort_if_invalid_pointer_argument (b);
+    abort_if_invalid_pointer_argument (gx);
+    abort_if_invalid_pointer_argument (gy);
+    abort_if_invalid_pointer_argument (order);
+    abort_if_invalid_pointer_argument (cofactor);
+
+    // qx, qy, d and seed are optional
 
     JNIEnv* env = GetJNIEnv();
 
index 453dc5751bce79dada9025ade44fbaf5830ee1f4..d063972460c974ada7844ca9acc9c19975accd51 100644 (file)
@@ -8,6 +8,11 @@
 
 int32_t AndroidCryptoNative_EcdhDeriveKey(EC_KEY* ourKey, EC_KEY* peerKey, uint8_t* resultKey, int32_t bufferLength, int32_t* usedBufferLength)
 {
+    abort_if_invalid_pointer_argument (ourKey);
+    abort_if_invalid_pointer_argument (peerKey);
+    abort_if_invalid_pointer_argument (resultKey);
+    abort_if_invalid_pointer_argument (usedBufferLength);
+
     JNIEnv* env = GetJNIEnv();
 
     jstring algorithmName = JSTRING("ECDH");
index d42a6041d98f951a3f5f5af9c3f193c90bc4fa0c..7ef02023c110239535680a342ea7528319f5c701 100644 (file)
@@ -19,13 +19,10 @@ static jobject GetEcDsaSignatureObject(JNIEnv* env)
 
 int32_t AndroidCryptoNative_EcDsaSign(const uint8_t* dgst, int32_t dgstlen, uint8_t* sig, int32_t* siglen, EC_KEY* key)
 {
-    assert(dgst);
-    assert(sig);
-    assert(key);
-    if (!siglen)
-    {
-        return FAIL;
-    }
+    abort_if_invalid_pointer_argument (dgst);
+    abort_if_invalid_pointer_argument (sig);
+    abort_if_invalid_pointer_argument (key);
+    abort_if_invalid_pointer_argument (siglen);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -50,9 +47,10 @@ int32_t AndroidCryptoNative_EcDsaSign(const uint8_t* dgst, int32_t dgstlen, uint
 
 int32_t AndroidCryptoNative_EcDsaVerify(const uint8_t* dgst, int32_t dgstlen, const uint8_t* sig, int32_t siglen, EC_KEY* key)
 {
-    assert(dgst);
-    assert(sig);
-    assert(key);
+    abort_if_invalid_pointer_argument (dgst);
+    abort_if_invalid_pointer_argument (sig);
+    abort_if_invalid_pointer_argument (key);
+
     JNIEnv* env = GetJNIEnv();
 
     jobject signatureObject = GetEcDsaSignatureObject(env);
@@ -70,6 +68,8 @@ int32_t AndroidCryptoNative_EcDsaVerify(const uint8_t* dgst, int32_t dgstlen, co
 
 int32_t AndroidCryptoNative_EcDsaSize(const EC_KEY* key)
 {
+    abort_if_invalid_pointer_argument (key);
+
     // The maximum size of a signature for the provided key is 2* bitlength of the order + extra bytes for the DER
     // encoding. The DER encoding is as follows (with R and S being the components of the signature and all lengths
     // being one byte width):
index f14bfc9f640cfc1173eff4959ae33bbb2f7565cb..612dade36b813920598326ff20a38a453a4416f1 100644 (file)
@@ -8,8 +8,8 @@
 
 EC_KEY* AndroidCryptoNative_NewEcKey(jobject curveParameters, jobject keyPair)
 {
-    assert(curveParameters);
-    assert(keyPair);
+    abort_if_invalid_pointer_argument (curveParameters);
+    abort_if_invalid_pointer_argument (keyPair);
 
     EC_KEY* keyInfo = malloc(sizeof(EC_KEY));
     memset(keyInfo, 0, sizeof(EC_KEY));
@@ -21,7 +21,7 @@ EC_KEY* AndroidCryptoNative_NewEcKey(jobject curveParameters, jobject keyPair)
 
 EC_KEY* AndroidCryptoNative_NewEcKeyFromKeys(JNIEnv *env, jobject /*ECPublicKey*/ publicKey, jobject /*ECPrivateKey*/ privateKey)
 {
-    assert(publicKey != NULL);
+    abort_if_invalid_pointer_argument (publicKey);
 
     if (!(*env)->IsInstanceOf(env, publicKey, g_ECPublicKeyClass))
         return NULL;
@@ -71,6 +71,8 @@ int32_t AndroidCryptoNative_EcKeyUpRef(EC_KEY* r)
 
 EC_KEY* AndroidCryptoNative_EcKeyCreateByOid(const char* oid)
 {
+    abort_if_invalid_pointer_argument (oid);
+
     JNIEnv* env = GetJNIEnv();
 
     // Older versions of Android don't support mapping an OID to a curve name,
@@ -164,6 +166,7 @@ int32_t AndroidCryptoNative_EcKeyGetSize(const EC_KEY* key, int32_t* keySize)
 
 int32_t AndroidCryptoNative_EcKeyGetCurveName(const EC_KEY* key, uint16_t** curveName)
 {
+    abort_if_invalid_pointer_argument (curveName);
     if (!g_ECParameterSpecGetCurveName)
     {
         // We can't get the curve name. Treat all curves as unnamed.
@@ -171,6 +174,7 @@ int32_t AndroidCryptoNative_EcKeyGetCurveName(const EC_KEY* key, uint16_t** curv
         return SUCCESS;
     }
 
+    abort_if_invalid_pointer_argument (key);
     JNIEnv* env = GetJNIEnv();
 
     jstring curveNameStr = (*env)->CallObjectMethod(env, key->curveParameters, g_ECParameterSpecGetCurveName);
index 2db14df4febf75b93f3b85ea75d108a70501e9e3..648e22ee6aa30952a7c868baccb55c8dd60fb131 100644 (file)
@@ -27,7 +27,15 @@ const char* CryptoNative_ErrReasonErrorString(uint64_t error)
     return "See logcat for more details.";
 }
 
+static const char see_logcat_message[] = "See logcat for more details.";
+#define SEE_LOGCAT_MESSAGE_LEN (int32_t)(sizeof(see_logcat_message))
+
 void CryptoNative_ErrErrorStringN(uint64_t e, char* buf, int32_t len)
 {
-    buf = "See logcat for more details.";
+    abort_if_invalid_pointer_argument (buf);
+    if (len <= 0) {
+        return;
+    }
+
+    memcpy (buf, see_logcat_message, len < SEE_LOGCAT_MESSAGE_LEN ? (size_t)len : SEE_LOGCAT_MESSAGE_LEN);
 }
index 0519e66b7b02f6e3d40e2557fa2ae9e53e4e2eab..d30c29d2cfe5fd56d82114b2fb8f0f4219ace7f3 100644 (file)
@@ -50,6 +50,8 @@ static jobject GetMessageDigestInstance(JNIEnv* env, intptr_t type)
 
 int32_t CryptoNative_EvpDigestOneShot(intptr_t type, void* source, int32_t sourceSize, uint8_t* md, uint32_t* mdSize)
 {
+    abort_if_invalid_pointer_argument (source);
+
     if (!type || !md || !mdSize || sourceSize < 0)
         return FAIL;
 
@@ -62,7 +64,7 @@ int32_t CryptoNative_EvpDigestOneShot(intptr_t type, void* source, int32_t sourc
     jbyteArray bytes = (*env)->NewByteArray(env, sourceSize);
     (*env)->SetByteArrayRegion(env, bytes, 0, sourceSize, (jbyte*) source);
     jbyteArray hashedBytes = (jbyteArray)(*env)->CallObjectMethod(env, mdObj, g_mdDigestWithInputBytes, bytes);
-    assert(hashedBytes && "MessageDigest.digest(...) was not expected to return null");
+    abort_unless(hashedBytes != NULL, "MessageDigest.digest(...) was not expected to return null");
 
     jsize hashedBytesLen = (*env)->GetArrayLength(env, hashedBytes);
     (*env)->GetByteArrayRegion(env, hashedBytes, 0, hashedBytesLen, (jbyte*) md);
@@ -83,7 +85,7 @@ jobject CryptoNative_EvpMdCtxCreate(intptr_t type)
 
 int32_t CryptoNative_EvpDigestReset(jobject ctx, intptr_t type)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
 
     JNIEnv* env = GetJNIEnv();
     (*env)->CallVoidMethod(env, ctx, g_mdReset);
@@ -93,7 +95,9 @@ int32_t CryptoNative_EvpDigestReset(jobject ctx, intptr_t type)
 
 int32_t CryptoNative_EvpDigestUpdate(jobject ctx, void* d, int32_t cnt)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
+    if(cnt > 0)
+        abort_if_invalid_pointer_argument (d);
     JNIEnv* env = GetJNIEnv();
 
     jbyteArray bytes = (*env)->NewByteArray(env, cnt);
@@ -106,9 +110,11 @@ int32_t CryptoNative_EvpDigestUpdate(jobject ctx, void* d, int32_t cnt)
 
 static int32_t DigestFinal(JNIEnv* env, jobject ctx, uint8_t* md, uint32_t* s)
 {
+    abort_if_invalid_pointer_argument (md);
+
     // ctx.digest();
     jbyteArray bytes = (jbyteArray)(*env)->CallObjectMethod(env, ctx, g_mdDigest);
-    assert(bytes && "digest() was not expected to return null");
+    abort_unless(bytes != NULL, "digest() was not expected to return null");
     jsize bytesLen = (*env)->GetArrayLength(env, bytes);
     *s = (uint32_t)bytesLen;
     (*env)->GetByteArrayRegion(env, bytes, 0, bytesLen, (jbyte*) md);
@@ -118,7 +124,7 @@ static int32_t DigestFinal(JNIEnv* env, jobject ctx, uint8_t* md, uint32_t* s)
 
 int32_t CryptoNative_EvpDigestFinalEx(jobject ctx, uint8_t* md, uint32_t* s)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
 
     JNIEnv* env = GetJNIEnv();
     return DigestFinal(env, ctx, md, s);
@@ -126,7 +132,7 @@ int32_t CryptoNative_EvpDigestFinalEx(jobject ctx, uint8_t* md, uint32_t* s)
 
 int32_t CryptoNative_EvpDigestCurrent(jobject ctx, uint8_t* md, uint32_t* s)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
index 33a40c0480611c3645cabeee50dca71a7ec29664..b207ac66549e92a1c2fdc87532f97d53e4111467 100644 (file)
@@ -6,8 +6,9 @@
 
 jobject CryptoNative_HmacCreate(uint8_t* key, int32_t keyLen, intptr_t type)
 {
-    assert(key || (keyLen == 0));
-    assert(keyLen >= 0);
+    if (key != NULL && keyLen < 0) {
+        return NULL;
+    }
 
     // Mac mac = Mac.getInstance(algName);
     // SecretKeySpec key = new SecretKeySpec(key, algName);
@@ -46,14 +47,19 @@ jobject CryptoNative_HmacCreate(uint8_t* key, int32_t keyLen, intptr_t type)
     }
 
     jobject sksObj = (*env)->NewObject(env, g_sksClass, g_sksCtor, keyBytes, macName);
-    if (CheckJNIExceptions(env))
+    if (CheckJNIExceptions(env) || sksObj == NULL)
     {
+        if(sksObj == NULL)
+        {
+            LOG_WARN ("Unable to create an instance of SecretKeySpec");
+        }
+
         (*env)->DeleteLocalRef(env, keyBytes);
         (*env)->DeleteLocalRef(env, sksObj);
         (*env)->DeleteLocalRef(env, macName);
         return FAIL;
     }
-    assert(sksObj && "Unable to create an instance of SecretKeySpec");
+
     jobject macObj = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_MacClass, g_MacGetInstance, macName));
     (*env)->CallVoidMethod(env, macObj, g_MacInit, sksObj);
     (*env)->DeleteLocalRef(env, keyBytes);
@@ -79,6 +85,7 @@ int32_t CryptoNative_HmacUpdate(jobject ctx, uint8_t* data, int32_t len)
     if (!ctx)
         return FAIL;
 
+    abort_if_invalid_pointer_argument (data);
     JNIEnv* env = GetJNIEnv();
     jbyteArray dataBytes = (*env)->NewByteArray(env, len);
     (*env)->SetByteArrayRegion(env, dataBytes, 0, len, (jbyte*)data);
@@ -102,7 +109,7 @@ static int32_t DoFinal(JNIEnv* env, jobject mac, uint8_t* data, int32_t* len)
 
 int32_t CryptoNative_HmacFinal(jobject ctx, uint8_t* data, int32_t* len)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
 
     JNIEnv* env = GetJNIEnv();
     return DoFinal(env, ctx, data, len);
@@ -110,7 +117,7 @@ int32_t CryptoNative_HmacFinal(jobject ctx, uint8_t* data, int32_t* len)
 
 int32_t CryptoNative_HmacCurrent(jobject ctx, uint8_t* data, int32_t* len)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
index 162c0fbf74f6eccdd3203de77e66ff1b62f925a8..3d9374637b6b46379c4d742bc7061d27a3d4c778 100644 (file)
@@ -498,10 +498,10 @@ jclass GetClassGRef(JNIEnv *env, const char* name)
     jclass klass = NULL;
     if (!TryGetClassGRef(env, name, &klass))
     {
-        LOG_ERROR("class %s was not found", name);
+        LOG_FATAL("class %s was not found", name);
+        abort ();
     }
 
-    assert(klass);
     return klass;
 }
 
@@ -570,10 +570,7 @@ jmethodID GetMethod(JNIEnv *env, bool isStatic, jclass klass, const char* name,
 {
     LOG_DEBUG("Finding %s method", name);
     jmethodID mid = isStatic ? (*env)->GetStaticMethodID(env, klass, name, sig) : (*env)->GetMethodID(env, klass, name, sig);
-    if (!mid) {
-        LOG_ERROR("method %s %s was not found", name, sig);
-        assert(mid);
-    }
+    abort_unless(mid != NULL, "method %s %s was not found", name, sig);
     return mid;
 }
 
@@ -593,10 +590,7 @@ jfieldID GetField(JNIEnv *env, bool isStatic, jclass klass, const char* name, co
 {
     LOG_DEBUG("Finding %s field", name);
     jfieldID fid = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig);
-    if (!fid) {
-        LOG_ERROR("field %s %s was not found", name, sig);
-        assert(fid);
-    }
+    abort_unless(fid != NULL, "field %s %s was not found", name, sig);
     return fid;
 }
 
@@ -618,7 +612,7 @@ make_key()
 
 JNIEnv* GetJNIEnv()
 {
-    JNIEnv *env;
+    JNIEnv *env = NULL;
     (*gJvm)->GetEnv(gJvm, (void**)&env, JNI_VERSION_1_6);
     if (env)
         return env;
@@ -628,8 +622,7 @@ JNIEnv* GetJNIEnv()
     LOG_DEBUG("Registering JNI thread detach. env ptr %p. Key: %ld", (void*)env, (long)threadLocalEnvKey);
     pthread_setspecific(threadLocalEnvKey, env);
 
-    assert(ret == JNI_OK && "Unable to attach thread to JVM");
-    (void)ret;
+    abort_unless(ret == JNI_OK, "Unable to attach thread to JVM");
     return env;
 }
 
index 8edd030da9e74efe295125e0760914fbc68ca823..c109c3827e524a899902b45d9f85eeaca2ac6b46 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <jni.h>
 #include <android/log.h>
-#include <assert.h>
 #include <stdlib.h>
 #include "pal_safecrt.h"
 
@@ -469,7 +468,9 @@ extern jmethodID g_KeyAgreementGenerateSecret;
 // Logging helpers
 #define LOG_DEBUG(fmt, ...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
 #define LOG_INFO(fmt, ...) ((void)__android_log_print(ANDROID_LOG_INFO, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
+#define LOG_WARN(fmt, ...) ((void)__android_log_print(ANDROID_LOG_WARN, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
 #define LOG_ERROR(fmt, ...) ((void)__android_log_print(ANDROID_LOG_ERROR, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
+#define LOG_FATAL(fmt, ...) ((void)__android_log_print(ANDROID_LOG_FATAL, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
 
 // JNI helpers - assume there is a JNIEnv* variable named env
 #define JSTRING(str) ((jstring)(*env)->NewStringUTF(env, str))
index 67018229a46bb1bb7b64b2fd4bb1d9ed918acd83..468067bf7a5484a9684e829f0364996581931452 100644 (file)
@@ -11,11 +11,12 @@ int32_t CryptoNative_EnsureOpenSslInitialized()
 
 int32_t CryptoNative_GetRandomBytes(uint8_t* buff, int32_t len)
 {
-    assert(g_randClass);
-    assert(g_randCtor);
+    // JNI requires `buff` to be not NULL when passed to `{Get,Set}ByteArrayRegion`
+    abort_unless(buff != NULL, "The 'buff' parameter must be a valid pointer");
+
     JNIEnv* env = GetJNIEnv();
     jobject randObj = (*env)->NewObject(env, g_randClass, g_randCtor);
-    assert(randObj && "Unable to create an instance of java/security/SecureRandom");
+    abort_unless(randObj != NULL,"Unable to create an instance of java/security/SecureRandom");
 
     jbyteArray buffArray = (*env)->NewByteArray(env, len);
     (*env)->SetByteArrayRegion(env, buffArray, 0, len, (jbyte*)buff);
index 546863296473051644cc8f07e60c5494b4111a5d..59264b34ab602254c65252d7e6e02e05ce757f9d 100644 (file)
@@ -47,7 +47,10 @@ PALEXPORT void AndroidCryptoNative_RsaDestroy(RSA* rsa)
 
 PALEXPORT int32_t AndroidCryptoNative_RsaPublicEncrypt(int32_t flen, uint8_t* from, uint8_t* to, RSA* rsa, RsaPadding padding)
 {
-    assert(rsa != NULL);
+    abort_if_invalid_pointer_argument (from);
+    abort_if_invalid_pointer_argument (to);
+    abort_if_invalid_pointer_argument (rsa);
+
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = RSA_FAIL;
@@ -91,6 +94,9 @@ PALEXPORT int32_t AndroidCryptoNative_RsaPrivateDecrypt(int32_t flen, uint8_t* f
     if (!rsa->privateKey)
         return RSA_FAIL;
 
+    abort_if_invalid_pointer_argument (to);
+    abort_if_invalid_pointer_argument (from);
+
     JNIEnv* env = GetJNIEnv();
 
     jobject algName;
@@ -180,6 +186,9 @@ PALEXPORT int32_t AndroidCryptoNative_RsaSignPrimitive(int32_t flen, uint8_t* fr
         return RSA_FAIL;
     }
 
+    abort_if_invalid_pointer_argument (to);
+    abort_if_invalid_pointer_argument (from);
+
     JNIEnv* env = GetJNIEnv();
 
     jobject algName = JSTRING("RSA/ECB/NoPadding");
@@ -212,6 +221,9 @@ PALEXPORT int32_t AndroidCryptoNative_RsaVerificationPrimitive(int32_t flen, uin
     if (!rsa)
         return RSA_FAIL;
 
+    abort_if_invalid_pointer_argument (to);
+    abort_if_invalid_pointer_argument (from);
+
     JNIEnv* env = GetJNIEnv();
 
     jobject algName = JSTRING("RSA/ECB/NoPadding");
index 50da0effb4d2883dccfa12e3cee93f6d6f6e4c6d..72a389fbabe237dd983ec182c4ad86018c2e4ad6 100644 (file)
@@ -11,10 +11,10 @@ int32_t AndroidCryptoNative_SignWithSignatureObject(JNIEnv* env,
                                                     uint8_t* sig,
                                                     int32_t* siglen)
 {
-    assert(dgst);
-    assert(sig);
-    assert(signatureObject);
-    assert(privateKey);
+    abort_if_invalid_pointer_argument (dgst);
+    abort_if_invalid_pointer_argument (sig);
+    abort_if_invalid_pointer_argument (signatureObject);
+    abort_if_invalid_pointer_argument (privateKey);
     if (!siglen)
     {
         return FAIL;
@@ -49,10 +49,10 @@ int32_t AndroidCryptoNative_VerifyWithSignatureObject(JNIEnv* env,
                                                       const uint8_t* sig,
                                                       int32_t siglen)
 {
-    assert(dgst);
-    assert(sig);
-    assert(signatureObject);
-    assert(publicKey);
+    abort_if_invalid_pointer_argument (dgst);
+    abort_if_invalid_pointer_argument (sig);
+    abort_if_invalid_pointer_argument (signatureObject);
+    abort_if_invalid_pointer_argument (publicKey);
 
     (*env)->CallVoidMethod(env, signatureObject, g_SignatureInitVerify, publicKey);
     ON_EXCEPTION_PRINT_AND_GOTO(error);
index 7f82df1e986900bd81faa002e77f29c24ca10186..319cfd47b50291a049006a8623df7a9571feeb71 100644 (file)
@@ -245,9 +245,6 @@ static PAL_SSLStreamStatus DoUnwrap(JNIEnv* env, SSLStream* sslStream, int* hand
 
 static PAL_SSLStreamStatus DoHandshake(JNIEnv* env, SSLStream* sslStream)
 {
-    assert(env != NULL);
-    assert(sslStream != NULL);
-
     PAL_SSLStreamStatus status = SSLStreamStatus_OK;
     int handshakeStatus =
         GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeStatus));
@@ -275,7 +272,6 @@ static PAL_SSLStreamStatus DoHandshake(JNIEnv* env, SSLStream* sslStream)
 
 static void FreeSSLStream(JNIEnv* env, SSLStream* sslStream)
 {
-    assert(sslStream != NULL);
     ReleaseGRef(env, sslStream->sslContext);
     ReleaseGRef(env, sslStream->sslEngine);
     ReleaseGRef(env, sslStream->sslSession);
@@ -309,6 +305,9 @@ static int32_t AddCertChainToStore(JNIEnv* env,
                                    jobject* /*X509Certificate[]*/ certs,
                                    int32_t certsLen)
 {
+    abort_if_invalid_pointer_argument (pkcs8PrivateKey);
+    abort_if_invalid_pointer_argument (certs);
+
     int32_t ret = FAIL;
     INIT_LOCALS(loc, keyBytes, keySpec, algorithmName, keyFactory, privateKey, certArray, alias);
 
@@ -428,10 +427,10 @@ cleanup:
 int32_t AndroidCryptoNative_SSLStreamInitialize(
     SSLStream* sslStream, bool isServer, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize)
 {
-    assert(sslStream != NULL);
-    assert(sslStream->sslContext != NULL);
-    assert(sslStream->sslEngine == NULL);
-    assert(sslStream->sslSession == NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_unless(sslStream->sslContext != NULL, "sslContext is NULL in SSL stream");
+    abort_unless(sslStream->sslEngine == NULL, "sslEngine is NOT NULL in SSL stream");
+    abort_unless(sslStream->sslSession == NULL, "sslSession is NOT NULL in SSL stream");
 
     int32_t ret = FAIL;
     JNIEnv* env = GetJNIEnv();
@@ -478,8 +477,8 @@ exit:
 
 int32_t AndroidCryptoNative_SSLStreamSetTargetHost(SSLStream* sslStream, char* targetHost)
 {
-    assert(sslStream != NULL);
-    assert(targetHost != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (targetHost);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -514,7 +513,7 @@ cleanup:
 
 PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
     JNIEnv* env = GetJNIEnv();
 
     // sslEngine.beginHandshake();
@@ -528,8 +527,8 @@ PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream)
 PAL_SSLStreamStatus
 AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream, uint8_t* buffer, int32_t length, int32_t* read)
 {
-    assert(sslStream != NULL);
-    assert(read != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (read);
 
     jbyteArray data = NULL;
     JNIEnv* env = GetJNIEnv();
@@ -602,7 +601,7 @@ cleanup:
 
 PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamWrite(SSLStream* sslStream, uint8_t* buffer, int32_t length)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
 
     JNIEnv* env = GetJNIEnv();
     PAL_SSLStreamStatus ret = SSLStreamStatus_Error;
@@ -654,7 +653,8 @@ void AndroidCryptoNative_SSLStreamRelease(SSLStream* sslStream)
 
 int32_t AndroidCryptoNative_SSLStreamGetApplicationProtocol(SSLStream* sslStream, uint8_t* out, int32_t* outLen)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (outLen);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
@@ -683,8 +683,8 @@ cleanup:
 
 int32_t AndroidCryptoNative_SSLStreamGetCipherSuite(SSLStream* sslStream, uint16_t** out)
 {
-    assert(sslStream != NULL);
-    assert(out != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (out);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
@@ -704,8 +704,8 @@ cleanup:
 
 int32_t AndroidCryptoNative_SSLStreamGetProtocol(SSLStream* sslStream, uint16_t** out)
 {
-    assert(sslStream != NULL);
-    assert(out != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (out);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
@@ -725,7 +725,7 @@ cleanup:
 
 jobject /*X509Certificate*/ AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLStream* sslStream)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
 
     JNIEnv* env = GetJNIEnv();
     jobject ret = NULL;
@@ -753,8 +753,9 @@ cleanup:
 
 void AndroidCryptoNative_SSLStreamGetPeerCertificates(SSLStream* sslStream, jobject** out, int32_t* outLen)
 {
-    assert(sslStream != NULL);
-    assert(out != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (out);
+    abort_if_invalid_pointer_argument (outLen);
 
     JNIEnv* env = GetJNIEnv();
     *out = NULL;
@@ -788,7 +789,7 @@ cleanup:
 
 void AndroidCryptoNative_SSLStreamRequestClientAuthentication(SSLStream* sslStream)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
     JNIEnv* env = GetJNIEnv();
 
     // sslEngine.setWantClientAuth(true);
@@ -799,9 +800,13 @@ int32_t AndroidCryptoNative_SSLStreamSetApplicationProtocols(SSLStream* sslStrea
                                                              ApplicationProtocolData* protocolData,
                                                              int32_t count)
 {
-    assert(sslStream != NULL);
-    assert(protocolData != NULL);
-    assert(AndroidCryptoNative_SSLSupportsApplicationProtocolsConfiguration());
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (protocolData);
+
+    if (!AndroidCryptoNative_SSLSupportsApplicationProtocolsConfiguration()) {
+        LOG_ERROR ("SSL does not support application protocols configuration");
+        return FAIL;
+    }
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
@@ -860,7 +865,8 @@ static jstring GetSslProtocolAsString(JNIEnv* env, PAL_SslProtocol protocol)
 int32_t
 AndroidCryptoNative_SSLStreamSetEnabledProtocols(SSLStream* sslStream, PAL_SslProtocol* protocols, int32_t count)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (protocols);
 
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
@@ -887,8 +893,8 @@ cleanup:
 
 bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hostname)
 {
-    assert(sslStream != NULL);
-    assert(hostname != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
+    abort_if_invalid_pointer_argument (hostname);
     JNIEnv* env = GetJNIEnv();
 
     bool ret = false;
@@ -907,7 +913,7 @@ bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hos
 
 bool AndroidCryptoNative_SSLStreamShutdown(SSLStream* sslStream)
 {
-    assert(sslStream != NULL);
+    abort_if_invalid_pointer_argument (sslStream);
     JNIEnv* env = GetJNIEnv();
 
     PAL_SSLStreamStatus status = Close(env, sslStream);
index f7dc194895b9558b0c76393cc2c060706eded03c..f552371bb8d9105f0b9b00d66302e3835e56eb42 100644 (file)
@@ -19,7 +19,9 @@ static void FindCertStart(const uint8_t** buffer, int32_t* len);
 // Handles both DER and PEM formats
 jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t* buf, int32_t len)
 {
-    assert(buf != NULL && len > 0);
+    abort_if_invalid_pointer_argument (buf);
+    abort_if_negative_integer_argument (len);
+
     JNIEnv* env = GetJNIEnv();
 
     jobject ret = NULL;
@@ -54,7 +56,7 @@ cleanup:
 // Encodes as DER format
 int32_t AndroidCryptoNative_X509Encode(jobject /*X509Certificate*/ cert, uint8_t* out, int32_t* outLen)
 {
-    assert(cert != NULL);
+    abort_if_invalid_pointer_argument (cert);
     JNIEnv* env = GetJNIEnv();
     int32_t ret = FAIL;
 
@@ -73,8 +75,10 @@ int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t* buf,
                                                  jobject /*X509Certificate*/* out,
                                                  int32_t* outLen)
 {
-    assert(buf != NULL && bufLen > 0);
-    assert(outLen != NULL);
+    abort_if_invalid_pointer_argument (buf);
+    abort_if_negative_integer_argument (bufLen);
+    abort_if_invalid_pointer_argument (outLen);
+
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -149,8 +153,9 @@ int32_t AndroidCryptoNative_X509ExportPkcs7(jobject* /*X509Certificate[]*/ certs
                                             uint8_t* out,
                                             int32_t* outLen)
 {
-    assert(certs != NULL && certsLen > 0);
-    assert(outLen != NULL);
+    abort_if_invalid_pointer_argument (certs);
+    abort_if_negative_integer_argument (certsLen);
+
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -189,7 +194,9 @@ cleanup:
 
 PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t* buf, int32_t len)
 {
-    assert(buf != NULL && len > 0);
+    abort_if_invalid_pointer_argument (buf);
+    abort_if_negative_integer_argument (len);
+
     JNIEnv* env = GetJNIEnv();
 
     PAL_X509ContentType ret = PAL_X509Unknown;
@@ -242,7 +249,7 @@ cleanup:
 
 void* AndroidCryptoNative_X509PublicKey(jobject /*X509Certificate*/ cert, PAL_KeyAlgorithm algorithm)
 {
-    assert(cert != NULL);
+    abort_if_invalid_pointer_argument (cert);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -274,6 +281,9 @@ void* AndroidCryptoNative_X509PublicKey(jobject /*X509Certificate*/ cert, PAL_Ke
 
 static int32_t PopulateByteArray(JNIEnv* env, jbyteArray source, uint8_t* dest, int32_t* len)
 {
+    abort_if_invalid_pointer_argument (source);
+    abort_if_invalid_pointer_argument (len);
+
     jsize bytesLen = (*env)->GetArrayLength(env, source);
 
     bool insufficientBuffer = *len < bytesLen;
@@ -281,15 +291,15 @@ static int32_t PopulateByteArray(JNIEnv* env, jbyteArray source, uint8_t* dest,
     if (insufficientBuffer)
         return INSUFFICIENT_BUFFER;
 
+    if(dest == NULL)
+        return SUCCESS; // managed code calls us with `dest` == NULL if it needs to learn the buffer size, it's not an
+                        // error
     (*env)->GetByteArrayRegion(env, source, 0, bytesLen, (jbyte*)dest);
     return CheckJNIExceptions(env) ? FAIL : SUCCESS;
 }
 
 static void FindCertStart(const uint8_t** buffer, int32_t* len)
 {
-    assert(buffer != NULL && *buffer != NULL);
-    assert(*len >= 0);
-
     if (iscntrl(**buffer) && !isspace(**buffer))
     {
         // If the character is a control character that isn't whitespace, then we're probably using a DER encoding
index adc736b0af11f6c6371e67dffbd11e197198067a..c28baccfe31b7c7ce45b6ffae8e3d8648d84a5ec 100644 (file)
@@ -29,8 +29,13 @@ X509ChainContext* AndroidCryptoNative_X509ChainCreateContext(jobject /*X509Certi
                                                              jobject* /*X509Certificate[]*/ extraStore,
                                                              int32_t extraStoreLen)
 {
-    assert(cert != NULL);
-    assert(extraStore != NULL || extraStoreLen == 0);
+    abort_if_invalid_pointer_argument (cert);
+
+    if (extraStore == NULL && extraStoreLen != 0) {
+        LOG_WARN ("No extra store pointer provided, but extra store length is %d", extraStoreLen);
+        extraStoreLen = 0;
+    }
+
     JNIEnv* env = GetJNIEnv();
 
     X509ChainContext* ret = NULL;
@@ -106,7 +111,7 @@ void AndroidCryptoNative_X509ChainDestroyContext(X509ChainContext* ctx)
 
 int32_t AndroidCryptoNative_X509ChainBuild(X509ChainContext* ctx, int64_t timeInMsFromUnixEpoch)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -151,7 +156,7 @@ cleanup:
 
 int32_t AndroidCryptoNative_X509ChainGetCertificateCount(X509ChainContext* ctx)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
     JNIEnv* env = GetJNIEnv();
 
     // List<Certificate> certPathList = certPath.getCertificates();
@@ -166,7 +171,7 @@ int32_t AndroidCryptoNative_X509ChainGetCertificates(X509ChainContext* ctx,
                                                      jobject* /*X509Certificate[]*/ certs,
                                                      int32_t certsLen)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -177,6 +182,8 @@ int32_t AndroidCryptoNative_X509ChainGetCertificates(X509ChainContext* ctx,
     if (certsLen < certCount + 1)
         goto cleanup;
 
+    abort_if_invalid_pointer_argument (certs);
+
     // for (int i = 0; i < certPathList.size(); ++i) {
     //     Certificate cert = certPathList.get(i);
     //     certs[i] = cert;
@@ -210,7 +217,9 @@ cleanup:
 
 int32_t AndroidCryptoNative_X509ChainGetErrorCount(X509ChainContext* ctx)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument(ctx);
+    abort_unless(ctx->errorList != NULL, "errorList is NULL in X509ChainContext");
+
     JNIEnv* env = GetJNIEnv();
     int32_t count = (*env)->CallIntMethod(env, ctx->errorList, g_CollectionSize);
     if (ctx->revocationErrorList != NULL)
@@ -342,7 +351,9 @@ static void PopulateValidationError(JNIEnv* env, jobject error, bool isRevocatio
 
 int32_t AndroidCryptoNative_X509ChainGetErrors(X509ChainContext* ctx, ValidationError* errors, int32_t errorsLen)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
+    abort_unless(ctx->errorList != NULL, "errorList is NULL in X509ChainContext");
+
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -354,6 +365,8 @@ int32_t AndroidCryptoNative_X509ChainGetErrors(X509ChainContext* ctx, Validation
     if (errorsLen < errorCount + revocationErrorCount)
         goto exit;
 
+    abort_if_invalid_pointer_argument (errors);
+
     // for (int i = 0; i < errorList.size(); ++i) {
     //     Throwable error = errorList.get(i);
     //     << populate errors[i] >>
@@ -370,12 +383,14 @@ int32_t AndroidCryptoNative_X509ChainGetErrors(X509ChainContext* ctx, Validation
     //     Throwable error = revocationErrorList.get(i);
     //     << populate errors[i] >>
     // }
-    for (int32_t i = 0; i < revocationErrorCount; ++i)
-    {
-        jobject error = (*env)->CallObjectMethod(env, ctx->revocationErrorList, g_ListGet, i);
-        ON_EXCEPTION_PRINT_AND_GOTO(exit);
-        PopulateValidationError(env, error, true /*isRevocationError*/, &errors[errorCount + i]);
-        (*env)->DeleteLocalRef(env, error);
+    if(ctx->revocationErrorList != NULL) { // double check, don't just trust the count to protect us from a segfault
+        for (int32_t i = 0; i < revocationErrorCount; ++i)
+        {
+            jobject error = (*env)->CallObjectMethod(env, ctx->revocationErrorList, g_ListGet, i);
+            ON_EXCEPTION_PRINT_AND_GOTO(exit);
+            PopulateValidationError(env, error, true /*isRevocationError*/, &errors[errorCount + i]);
+            (*env)->DeleteLocalRef(env, error);
+        }
     }
 
     ret = SUCCESS;
@@ -388,7 +403,10 @@ int32_t AndroidCryptoNative_X509ChainSetCustomTrustStore(X509ChainContext* ctx,
                                                          jobject* /*X509Certificate*/ customTrustStore,
                                                          int32_t customTrustStoreLen)
 {
-    assert(ctx != NULL);
+    abort_if_invalid_pointer_argument (ctx);
+    if (customTrustStoreLen > 0) {
+        abort_if_invalid_pointer_argument (customTrustStore);
+    }
     JNIEnv* env = GetJNIEnv();
 
     // HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>(customTrustStoreLen);
@@ -453,8 +471,8 @@ static int32_t ValidateWithRevocation(JNIEnv* env,
                                       PAL_X509RevocationMode revocationMode,
                                       PAL_X509RevocationFlag revocationFlag)
 {
-    assert(ctx != NULL);
-    assert(validator != NULL);
+    abort_if_invalid_pointer_argument (ctx);
+    abort_if_invalid_pointer_argument (validator);
 
     int32_t ret = FAIL;
     INIT_LOCALS(loc, certPathFromAnchor, options, checker, result, ex);
@@ -514,7 +532,7 @@ static int32_t ValidateWithRevocation(JNIEnv* env,
     }
     else
     {
-        assert(revocationFlag == X509RevocationFlag_ExcludeRoot);
+        abort_unless(revocationFlag == X509RevocationFlag_ExcludeRoot, "revocationFlag must be X509RevocationFlag_ExcludeRoot");
         certPathToUse = ctx->certPath;
     }
 
@@ -562,8 +580,8 @@ int32_t AndroidCryptoNative_X509ChainValidate(X509ChainContext* ctx,
                                               PAL_X509RevocationFlag revocationFlag,
                                               bool* checkedRevocation)
 {
-    assert(ctx != NULL);
-    assert(checkedRevocation != NULL);
+    abort_if_invalid_pointer_argument (ctx);
+    abort_if_invalid_pointer_argument (checkedRevocation);
     JNIEnv* env = GetJNIEnv();
 
     *checkedRevocation = false;
index 9724e8af2f4afaa4265910804f5ca38742c448b4..1e047b2bd2681dd747b3a4aee4d6dd47defa43a2 100644 (file)
@@ -89,8 +89,9 @@ int32_t AndroidCryptoNative_X509StoreAddCertificate(jobject /*KeyStore*/ store,
                                                     jobject /*X509Certificate*/ cert,
                                                     const char* hashString)
 {
-    assert(store != NULL);
-    assert(cert != NULL);
+    abort_if_invalid_pointer_argument (store);
+    abort_if_invalid_pointer_argument (cert);
+    abort_if_invalid_pointer_argument (hashString);
 
     JNIEnv* env = GetJNIEnv();
 
@@ -124,9 +125,10 @@ int32_t AndroidCryptoNative_X509StoreAddCertificateWithPrivateKey(jobject /*KeyS
                                                                   PAL_KeyAlgorithm algorithm,
                                                                   const char* hashString)
 {
-    assert(store != NULL);
-    assert(cert != NULL);
-    assert(key != NULL);
+    abort_if_invalid_pointer_argument (store);
+    abort_if_invalid_pointer_argument (cert);
+    abort_if_invalid_pointer_argument (key);
+    abort_if_invalid_pointer_argument (hashString);
 
     int32_t ret = FAIL;
     JNIEnv* env = GetJNIEnv();
@@ -212,8 +214,9 @@ bool AndroidCryptoNative_X509StoreContainsCertificate(jobject /*KeyStore*/ store
                                                       jobject /*X509Certificate*/ cert,
                                                       const char* hashString)
 {
-    assert(store != NULL);
-    assert(cert != NULL);
+    abort_if_invalid_pointer_argument (store);
+    abort_if_invalid_pointer_argument (cert);
+    abort_if_invalid_pointer_argument (hashString);
 
     JNIEnv* env = GetJNIEnv();
     jstring alias = JSTRING(hashString);
@@ -319,8 +322,8 @@ int32_t AndroidCryptoNative_X509StoreEnumerateCertificates(jobject /*KeyStore*/
                                                            EnumCertificatesCallback cb,
                                                            void* context)
 {
-    assert(store != NULL);
-    assert(cb != NULL);
+    abort_if_invalid_pointer_argument (store);
+    abort_if_invalid_pointer_argument (cb);
 
     JNIEnv* env = GetJNIEnv();
     return EnumerateCertificates(env, store, cb, context);
@@ -391,7 +394,7 @@ int32_t AndroidCryptoNative_X509StoreEnumerateTrustedCertificates(bool systemOnl
                                                                   EnumTrustedCertificatesCallback cb,
                                                                   void* context)
 {
-    assert(cb != NULL);
+    abort_if_invalid_pointer_argument (cb);
     JNIEnv* env = GetJNIEnv();
 
     int32_t ret = FAIL;
@@ -435,7 +438,7 @@ int32_t AndroidCryptoNative_X509StoreRemoveCertificate(jobject /*KeyStore*/ stor
                                                        jobject /*X509Certificate*/ cert,
                                                        const char* hashString)
 {
-    assert(store != NULL);
+    abort_if_invalid_pointer_argument (store);
 
     JNIEnv* env = GetJNIEnv();