#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")))
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);
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();
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);
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();
CipherCtx* AndroidCryptoNative_CipherCreatePartial(CipherInfo* type)
{
+ abort_if_invalid_pointer_argument (type);
+
JNIEnv* env = GetJNIEnv();
jobject algName = GetAlgorithmName(env, type);
if (!algName)
// 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;
}
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);
// 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);
if (!ctx)
return FAIL;
+ abort_if_invalid_pointer_argument(outm);
+ abort_if_invalid_pointer_argument(outl);
+
JNIEnv* env = GetJNIEnv();
*outl = 0;
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);
static jobject GetQParameter(JNIEnv* env, jobject dsa)
{
- assert(dsa);
+ abort_if_invalid_pointer_argument (dsa);
jobject ret = NULL;
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
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);
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;
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);
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();
uint8_t* x,
int32_t xLength)
{
- if (!outDsa)
- {
- assert(false);
- return 0;
- }
+ abort_if_invalid_pointer_argument (outDsa);
JNIEnv* env = GetJNIEnv();
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();
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);
}
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);
uint8_t* d,
int32_t dLength)
{
- if (!key || !oid)
- {
- assert(false);
- return 0;
- }
+ abort_if_invalid_pointer_argument (key);
*key = NULL;
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();
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");
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();
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);
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):
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));
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;
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,
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.
return SUCCESS;
}
+ abort_if_invalid_pointer_argument (key);
JNIEnv* env = GetJNIEnv();
jstring curveNameStr = (*env)->CallObjectMethod(env, key->curveParameters, g_ECParameterSpecGetCurveName);
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);
}
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;
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);
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);
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);
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);
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);
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;
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);
}
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);
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);
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);
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;
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;
}
{
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;
}
{
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;
}
JNIEnv* GetJNIEnv()
{
- JNIEnv *env;
+ JNIEnv *env = NULL;
(*gJvm)->GetEnv(gJvm, (void**)&env, JNI_VERSION_1_6);
if (env)
return env;
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;
}
#include <jni.h>
#include <android/log.h>
-#include <assert.h>
#include <stdlib.h>
#include "pal_safecrt.h"
// 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))
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);
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;
if (!rsa->privateKey)
return RSA_FAIL;
+ abort_if_invalid_pointer_argument (to);
+ abort_if_invalid_pointer_argument (from);
+
JNIEnv* env = GetJNIEnv();
jobject algName;
return RSA_FAIL;
}
+ abort_if_invalid_pointer_argument (to);
+ abort_if_invalid_pointer_argument (from);
+
JNIEnv* env = GetJNIEnv();
jobject algName = JSTRING("RSA/ECB/NoPadding");
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");
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;
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);
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));
static void FreeSSLStream(JNIEnv* env, SSLStream* sslStream)
{
- assert(sslStream != NULL);
ReleaseGRef(env, sslStream->sslContext);
ReleaseGRef(env, sslStream->sslEngine);
ReleaseGRef(env, sslStream->sslSession);
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);
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();
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();
PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream)
{
- assert(sslStream != NULL);
+ abort_if_invalid_pointer_argument (sslStream);
JNIEnv* env = GetJNIEnv();
// sslEngine.beginHandshake();
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();
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;
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;
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;
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;
jobject /*X509Certificate*/ AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLStream* sslStream)
{
- assert(sslStream != NULL);
+ abort_if_invalid_pointer_argument (sslStream);
JNIEnv* env = GetJNIEnv();
jobject ret = NULL;
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;
void AndroidCryptoNative_SSLStreamRequestClientAuthentication(SSLStream* sslStream)
{
- assert(sslStream != NULL);
+ abort_if_invalid_pointer_argument (sslStream);
JNIEnv* env = GetJNIEnv();
// sslEngine.setWantClientAuth(true);
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;
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;
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;
bool AndroidCryptoNative_SSLStreamShutdown(SSLStream* sslStream)
{
- assert(sslStream != NULL);
+ abort_if_invalid_pointer_argument (sslStream);
JNIEnv* env = GetJNIEnv();
PAL_SSLStreamStatus status = Close(env, sslStream);
// 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;
// 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;
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;
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;
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;
void* AndroidCryptoNative_X509PublicKey(jobject /*X509Certificate*/ cert, PAL_KeyAlgorithm algorithm)
{
- assert(cert != NULL);
+ abort_if_invalid_pointer_argument (cert);
JNIEnv* env = GetJNIEnv();
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;
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
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;
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;
int32_t AndroidCryptoNative_X509ChainGetCertificateCount(X509ChainContext* ctx)
{
- assert(ctx != NULL);
+ abort_if_invalid_pointer_argument (ctx);
JNIEnv* env = GetJNIEnv();
// List<Certificate> certPathList = certPath.getCertificates();
jobject* /*X509Certificate[]*/ certs,
int32_t certsLen)
{
- assert(ctx != NULL);
+ abort_if_invalid_pointer_argument (ctx);
JNIEnv* env = GetJNIEnv();
int32_t ret = FAIL;
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;
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)
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;
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] >>
// 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;
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);
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);
}
else
{
- assert(revocationFlag == X509RevocationFlag_ExcludeRoot);
+ abort_unless(revocationFlag == X509RevocationFlag_ExcludeRoot, "revocationFlag must be X509RevocationFlag_ExcludeRoot");
certPathToUse = ctx->certPath;
}
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;
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();
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();
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);
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);
EnumTrustedCertificatesCallback cb,
void* context)
{
- assert(cb != NULL);
+ abort_if_invalid_pointer_argument (cb);
JNIEnv* env = GetJNIEnv();
int32_t ret = FAIL;
jobject /*X509Certificate*/ cert,
const char* hashString)
{
- assert(store != NULL);
+ abort_if_invalid_pointer_argument (store);
JNIEnv* env = GetJNIEnv();