olm_jni_helper.cpp 7.19 KB
Newer Older
1
2
/*
 * Copyright 2016 OpenMarket Ltd
ylecollen's avatar
ylecollen committed
3
 * Copyright 2016 Vector Creations Ltd
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pedroGitt's avatar
pedroGitt committed
18
#include "olm_jni_helper.h"
19
#include "olm/olm.h"
20
#include <sys/time.h>
pedroGitt's avatar
pedroGitt committed
21
22

using namespace AndroidOlmSdk;
23
24
25
26
27
28
29

/**
* Init a buffer with a given number of random values.
* @param aBuffer2Ptr the buffer to be initialized
* @param aRandomSize the number of random values to apply
* @return true if operation succeed, false otherwise
**/
30
bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize)
31
{
ylecollen's avatar
ylecollen committed
32
33
    bool retCode = false;
    int bufferLen = aRandomSize*sizeof(uint8_t);
34

ylecollen's avatar
ylecollen committed
35
    if (!aBuffer2Ptr)
36
    {
ylecollen's avatar
ylecollen committed
37
38
        LOGE("## setRandomInBuffer(): failure - aBuffer=NULL");
    }
39
    else if (!aRandomSize)
ylecollen's avatar
ylecollen committed
40
41
42
43
44
45
46
47
48
49
    {
        LOGE("## setRandomInBuffer(): failure - random size=0");
    }
    else if (!(*aBuffer2Ptr = (uint8_t*)malloc(bufferLen)))
    {
        LOGE("## setRandomInBuffer(): failure - alloc mem OOM");
    }
    else
    {
        LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast<long unsigned int>(aRandomSize));
50

ylecollen's avatar
ylecollen committed
51
52
        // use the secureRandom class
        jclass cls = env->FindClass("java/security/SecureRandom");
53

ylecollen's avatar
ylecollen committed
54
        if (cls)
55
        {
ylecollen's avatar
ylecollen committed
56
57
58
59
60
61
62
63
64
            jobject newObj = 0;
            jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");
            jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V");

            if (constructor)
            {
                newObj = env->NewObject(cls, constructor);
                jbyteArray tempByteArray = env->NewByteArray(bufferLen);

ylecollen's avatar
ylecollen committed
65
                if (newObj && tempByteArray && !env->ExceptionOccurred())
ylecollen's avatar
ylecollen committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
                {
                    env->CallVoidMethod(newObj, nextByteMethod, tempByteArray);
                    jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL);

                    if (buffer)
                    {
                        memcpy(*aBuffer2Ptr, buffer, bufferLen);
                        retCode = true;

                        // clear tempByteArray to hide sensitive data.
                        memset(buffer, 0, bufferLen);
                        env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer);

                        // ensure that the buffer is released
                        env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT);
                    }
                }

                if (tempByteArray)
                {
                    env->DeleteLocalRef(tempByteArray);
                }

                if (newObj)
                {
                    env->DeleteLocalRef(newObj);
                }
            }
94
95
        }

ylecollen's avatar
ylecollen committed
96
97
        // debug purpose
        /*for(int i = 0; i < aRandomSize; i++)
98
        {
ylecollen's avatar
ylecollen committed
99
100
            LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
        }*/
101
    }
102

ylecollen's avatar
ylecollen committed
103
    return retCode;
104
105
106
}

/**
107
* Read the instance ID of the calling object.
108
109
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
110
* @param aCallingClass java calling clas name
111
112
* @return the instance ID if operation succeed, -1 if instance ID was not found.
**/
113
jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass)
114
{
ylecollen's avatar
ylecollen committed
115
    jlong instanceId = 0;
116
117

    if (aJniEnv)
118
    {
ylecollen's avatar
ylecollen committed
119
120
121
122
123
124
125
        jclass requiredClass = aJniEnv->FindClass(aCallingClass);
        jclass loaderClass = 0;

        if (requiredClass && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass)))
        {
            LOGE("## getAccountInstanceId() failure - invalid instance of");
        }
ylecollen's avatar
ylecollen committed
126
        else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject)))
ylecollen's avatar
ylecollen committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
        {
            jfieldID instanceIdField = aJniEnv->GetFieldID(loaderClass, "mNativeId", "J");

            if (instanceIdField)
            {
                instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
                LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId);
            }
            else
            {
                LOGE("## getInstanceId() ERROR! GetFieldID=null");
            }

             aJniEnv->DeleteLocalRef(loaderClass);
        }
        else
        {
            LOGE("## getInstanceId() ERROR! GetObjectClass=null");
        }
146
147
148
    }
    else
    {
ylecollen's avatar
ylecollen committed
149
        LOGE("## getInstanceId() ERROR! aJniEnv=NULL");
150
    }
ylecollen's avatar
ylecollen committed
151

ylecollen's avatar
ylecollen committed
152
    LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId);
ylecollen's avatar
ylecollen committed
153

ylecollen's avatar
ylecollen committed
154
    return instanceId;
155
156
157
}

/**
158
* Read the account instance ID of the calling object.
159
160
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
161
* @return the instance ID if operation succeed, -1 if instance ID was not found.
162
**/
163
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
164
{
ylecollen's avatar
ylecollen committed
165
166
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT);
    return instanceId;
167
}
168

169
170
171
172
173
174
175
176
/**
* Read the session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
ylecollen's avatar
ylecollen committed
177
178
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION);
    return instanceId;
179
180
181
182
183
184
185
186
187
188
}

/**
* Read the inbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
ylecollen's avatar
ylecollen committed
189
190
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION);
    return instanceId;
191
192
193
194
195
196
197
198
199
200
}

/**
* Read the outbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
ylecollen's avatar
ylecollen committed
201
202
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION);
    return instanceId;
203
204
}

205
206
207
208
209
210
/**
* Read the utility instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
211
212
jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
ylecollen's avatar
ylecollen committed
213
214
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY);
    return instanceId;
215
}