olm_jni_helper.cpp 7.29 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)
ylecollen's avatar
ylecollen committed
66
67
68
                {
                    env->CallVoidMethod(newObj, nextByteMethod, tempByteArray);

ylecollen's avatar
ylecollen committed
69
                    if (!env->ExceptionOccurred())
ylecollen's avatar
ylecollen committed
70
                    {
ylecollen's avatar
ylecollen committed
71
                        jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL);
ylecollen's avatar
ylecollen committed
72

ylecollen's avatar
ylecollen committed
73
74
75
76
                        if (buffer)
                        {
                            memcpy(*aBuffer2Ptr, buffer, bufferLen);
                            retCode = true;
ylecollen's avatar
ylecollen committed
77

ylecollen's avatar
ylecollen committed
78
79
80
81
82
83
84
                            // 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);
                        }
ylecollen's avatar
ylecollen committed
85
86
87
88
89
90
91
92
93
94
95
96
97
                    }
                }

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

                if (newObj)
                {
                    env->DeleteLocalRef(newObj);
                }
            }
98
99
        }

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

ylecollen's avatar
ylecollen committed
107
    return retCode;
108
109
110
}

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

    if (aJniEnv)
122
    {
ylecollen's avatar
ylecollen committed
123
124
125
126
127
128
129
        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
130
        else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject)))
ylecollen's avatar
ylecollen committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
        {
            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");
        }
150
151
152
    }
    else
    {
ylecollen's avatar
ylecollen committed
153
        LOGE("## getInstanceId() ERROR! aJniEnv=NULL");
154
    }
ylecollen's avatar
ylecollen committed
155

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

ylecollen's avatar
ylecollen committed
158
    return instanceId;
159
160
161
}

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

173
174
175
176
177
178
179
180
/**
* 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
181
182
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION);
    return instanceId;
183
184
185
186
187
188
189
190
191
192
}

/**
* 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
193
194
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION);
    return instanceId;
195
196
197
198
199
200
201
202
203
204
}

/**
* 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
205
206
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION);
    return instanceId;
207
208
}

209
210
211
212
213
214
/**
* 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.
**/
215
216
jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
ylecollen's avatar
ylecollen committed
217
218
    jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY);
    return instanceId;
219
}