Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
matrix-org
Olm
Commits
3c02c154
Commit
3c02c154
authored
Jan 18, 2017
by
Yannick LE COLLEN
Committed by
Richard van der Hoff
Jan 18, 2017
Browse files
Android: Add wrappers for export/import of inbound group sessions
parent
1761730d
Changes
5
Hide whitespace changes
Inline
Side-by-side
android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java
View file @
3c02c154
...
...
@@ -521,5 +521,107 @@ public class OlmGroupSessionTest {
assertTrue
(
0
!=
EXPECTED_ERROR_MESSAGE
.
length
());
assertTrue
(
EXPECTED_ERROR_MESSAGE
.
equals
(
exceptionMessage
));
}
/**
* Test the import/export functions.<br>
**/
@Test
public
void
test20TestInboundGroupSessionImportExport
()
{
String
sessionKey
=
"AgAAAAAwMTIzNDU2Nzg5QUJERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCREVGM"
+
"DEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlBQkRFRjAxMjM0NTY3ODlBQkNERUYwMTIzND"
+
"U2Nzg5QUJERUYwMTIzNDU2Nzg5QUJDREVGMDEyMw0bdg1BDq4Px/slBow06q8n/B9WBfw"
+
"WYyNOB8DlUmXGGwrFmaSb9bR/eY8xgERrxmP07hFmD9uqA2p8PMHdnV5ysmgufE6oLZ5+"
+
"8/mWQOW3VVTnDIlnwd8oHUYRuk8TCQ"
;
String
message
=
"AwgAEhAcbh6UpbByoyZxufQ+h2B+8XHMjhR69G8F4+qjMaFlnIXusJZX3r8LnRORG9T3D"
+
"XFdbVuvIWrLyRfm4i8QRbe8VPwGRFG57B1CtmxanuP8bHtnnYqlwPsD"
;
OlmInboundGroupSession
inboundGroupSession
=
null
;
try
{
inboundGroupSession
=
new
OlmInboundGroupSession
(
sessionKey
);
}
catch
(
Exception
e
)
{
assertTrue
(
"OlmInboundGroupSession failed "
+
e
.
getMessage
(),
false
);
}
boolean
isVerified
=
false
;
try
{
isVerified
=
inboundGroupSession
.
isVerified
();
}
catch
(
Exception
e
)
{
assertTrue
(
"isVerified failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(
isVerified
);
OlmInboundGroupSession
.
DecryptMessageResult
result
=
null
;
try
{
result
=
inboundGroupSession
.
decryptMessage
(
message
);
}
catch
(
Exception
e
)
{
assertTrue
(
"decryptMessage failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(
TextUtils
.
equals
(
result
.
mDecryptedMessage
,
"Message"
));
assertTrue
(
0
==
result
.
mIndex
);
String
export
=
null
;
try
{
export
=
inboundGroupSession
.
export
(
0
);
}
catch
(
Exception
e
)
{
assertTrue
(
"export failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(!
TextUtils
.
isEmpty
(
export
));
long
index
=
-
1
;
try
{
index
=
inboundGroupSession
.
getFirstKnownIndex
();
}
catch
(
Exception
e
)
{
assertTrue
(
"getFirstKnownIndex failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(
index
>=
0
);
inboundGroupSession
.
releaseSession
();
inboundGroupSession
=
null
;
OlmInboundGroupSession
inboundGroupSession2
=
null
;
try
{
inboundGroupSession2
=
inboundGroupSession
.
importSession
(
export
);
}
catch
(
Exception
e
)
{
assertTrue
(
"OlmInboundGroupSession failed "
+
e
.
getMessage
(),
false
);
}
try
{
isVerified
=
inboundGroupSession2
.
isVerified
();
}
catch
(
Exception
e
)
{
assertTrue
(
"isVerified failed "
+
e
.
getMessage
(),
false
);
}
assertFalse
(
isVerified
);
result
=
null
;
try
{
result
=
inboundGroupSession2
.
decryptMessage
(
message
);
}
catch
(
Exception
e
)
{
assertTrue
(
"decryptMessage failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(
TextUtils
.
equals
(
result
.
mDecryptedMessage
,
"Message"
));
assertTrue
(
0
==
result
.
mIndex
);
try
{
isVerified
=
inboundGroupSession2
.
isVerified
();
}
catch
(
Exception
e
)
{
assertTrue
(
"isVerified failed "
+
e
.
getMessage
(),
false
);
}
assertTrue
(
isVerified
);
inboundGroupSession2
.
releaseSession
();
}
}
android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
View file @
3c02c154
...
...
@@ -40,6 +40,9 @@ public class OlmException extends IOException {
public
static
final
int
EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION
=
201
;
public
static
final
int
EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER
=
202
;
public
static
final
int
EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION
=
203
;
public
static
final
int
EXCEPTION_CODE_INBOUND_GROUP_SESSION_FIRST_KNOWN_INDEX
=
204
;
public
static
final
int
EXCEPTION_CODE_INBOUND_GROUP_SESSION_IS_VERIFIED
=
205
;
public
static
final
int
EXCEPTION_CODE_INBOUND_GROUP_SESSION_EXPORT
=
206
;
public
static
final
int
EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION
=
300
;
public
static
final
int
EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION
=
301
;
...
...
android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
View file @
3c02c154
...
...
@@ -59,12 +59,24 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* @throws OlmException constructor failure
*/
public
OlmInboundGroupSession
(
String
aSessionKey
)
throws
OlmException
{
this
(
aSessionKey
,
false
);
}
/**
* Constructor.<br>
* Create and save a new native session instance ID and start a new inbound group session.
* The session key parameter is retrieved from an outbound group session.
* @param aSessionKey session key
* @param isImported true when the session key has been retrieved from a backup
* @throws OlmException constructor failure
*/
private
OlmInboundGroupSession
(
String
aSessionKey
,
boolean
isImported
)
throws
OlmException
{
if
(
TextUtils
.
isEmpty
(
aSessionKey
))
{
Log
.
e
(
LOG_TAG
,
"## initInboundGroupSession(): invalid session key"
);
throw
new
OlmException
(
OlmException
.
EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION
,
"invalid session key"
);
}
else
{
try
{
mNativeId
=
createNewSessionJni
(
aSessionKey
.
getBytes
(
"UTF-8"
));
mNativeId
=
createNewSessionJni
(
aSessionKey
.
getBytes
(
"UTF-8"
)
,
isImported
);
}
catch
(
Exception
e
)
{
throw
new
OlmException
(
OlmException
.
EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION
,
e
.
getMessage
());
}
...
...
@@ -76,9 +88,20 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* Since a C prt is returned as a jlong, special care will be taken
* to make the cast (OlmInboundGroupSession* to jlong) platform independent.
* @param aSessionKeyBuffer session key from an outbound session
* @param isImported true when the session key has been retrieved from a backup
* @return the initialized OlmInboundGroupSession* instance or throw an exception it fails.
**/
private
native
long
createNewSessionJni
(
byte
[]
aSessionKeyBuffer
);
private
native
long
createNewSessionJni
(
byte
[]
aSessionKeyBuffer
,
boolean
isImported
);
/**
* Create an OlmInboundGroupSession from its exported session data.
* @param exported the exported data
* @return the created OlmException
* @throws OlmException the failure reason
*/
public
static
OlmInboundGroupSession
importSession
(
String
exported
)
throws
OlmException
{
return
new
OlmInboundGroupSession
(
exported
,
true
);
}
/**
* Release native session and invalid its JAVA reference counter part.<br>
...
...
@@ -95,7 +118,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* Destroy the corresponding OLM inbound group session native object.<br>
* This method must ALWAYS be called when this JAVA instance
* is destroyed (ie. garbage collected) to prevent memory leak in native side.
* See {@link #createNewSessionJni(byte[])}.
* See {@link #createNewSessionJni(byte[]
, boolean
)}.
*/
private
native
void
releaseSessionJni
();
...
...
@@ -128,6 +151,86 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
*/
private
native
byte
[]
sessionIdentifierJni
();
/**
* Provides the first known index.
* @return the first known index.
* @throws OlmException the failure reason
*/
public
long
getFirstKnownIndex
()
throws
OlmException
{
long
index
=
0
;
try
{
index
=
firstKnownIndexJni
();
}
catch
(
Exception
e
)
{
Log
.
e
(
LOG_TAG
,
"## getFirstKnownIndex() failed "
+
e
.
getMessage
());
throw
new
OlmException
(
OlmException
.
EXCEPTION_CODE_INBOUND_GROUP_SESSION_FIRST_KNOWN_INDEX
,
e
.
getMessage
());
}
return
index
;
}
/**
* Provides the first known index.
* An exception is thrown if the operation fails.
* @return the first known index.
*/
private
native
long
firstKnownIndexJni
();
/**
* Tells if the session is verified.
* @return true if the session is verified
* @throws OlmException the failure reason
*/
public
boolean
isVerified
()
throws
OlmException
{
boolean
isVerified
;
try
{
isVerified
=
isVerifiedJni
();
}
catch
(
Exception
e
)
{
Log
.
e
(
LOG_TAG
,
"## isVerified() failed "
+
e
.
getMessage
());
throw
new
OlmException
(
OlmException
.
EXCEPTION_CODE_INBOUND_GROUP_SESSION_IS_VERIFIED
,
e
.
getMessage
());
}
return
isVerified
;
}
/**
* Tells if the session is verified.
* @return true if the session is verified
*/
private
native
boolean
isVerifiedJni
();
/**
* Export the session from a message index as String.
* @param messageIndex the message index
* @return the session as String
* @throws OlmException the failure reason
*/
public
String
export
(
long
messageIndex
)
throws
OlmException
{
String
result
=
null
;
try
{
byte
[]
bytesBuffer
=
exportJni
(
messageIndex
);
if
(
null
!=
bytesBuffer
)
{
result
=
new
String
(
bytesBuffer
,
"UTF-8"
);
}
}
catch
(
Exception
e
)
{
Log
.
e
(
LOG_TAG
,
"## export() failed "
+
e
.
getMessage
());
throw
new
OlmException
(
OlmException
.
EXCEPTION_CODE_INBOUND_GROUP_SESSION_EXPORT
,
e
.
getMessage
());
}
return
result
;
}
/**
* Exports the session as byte array from a message index
* An exception is thrown if the operation fails.
* @param messageIndex key used to encrypt the serialized session data
* @return the session saved as bytes array
*/
private
native
byte
[]
exportJni
(
long
messageIndex
);
/**
* Decrypt the message passed in parameter.<br>
* In case of error, null is returned and an error message description is provided in aErrorMsg.
...
...
@@ -156,7 +259,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* Decrypt a message.
* An exception is thrown if the operation fails.
* @param aEncryptedMsg the encrypted message
* @param aDecryptMessageResult the decryptMessage informaton
* @param aDecryptMessageResult the decryptMessage informat
i
on
* @return the decrypted message
*/
private
native
byte
[]
decryptMessageJni
(
byte
[]
aEncryptedMsg
,
DecryptMessageResult
aDecryptMessageResult
);
...
...
android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
View file @
3c02c154
...
...
@@ -54,9 +54,10 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env
* Since a C prt is returned as a jlong, special care will be taken
* to make the cast (OlmInboundGroupSession* => jlong) platform independent.
* @param aSessionKeyBuffer session key from an outbound session
* @param isImported true when the session key has been retrieved from a backup
* @return the initialized OlmInboundGroupSession* instance or throw an exception it fails.
**/
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
createNewSessionJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aSessionKeyBuffer
)
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
createNewSessionJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aSessionKeyBuffer
,
jboolean
isImported
)
{
const
char
*
errorMessage
=
NULL
;
OlmInboundGroupSession
*
sessionPtr
=
NULL
;
...
...
@@ -92,7 +93,18 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *
size_t
sessionKeyLength
=
(
size_t
)
env
->
GetArrayLength
(
aSessionKeyBuffer
);
LOGD
(
" ## createNewSessionJni(): sessionKeyLength=%lu"
,
static_cast
<
long
unsigned
int
>
(
sessionKeyLength
));
size_t
sessionResult
=
olm_init_inbound_group_session
(
sessionPtr
,
(
const
uint8_t
*
)
sessionKeyPtr
,
sessionKeyLength
);
size_t
sessionResult
;
if
(
JNI_FALSE
==
isImported
)
{
LOGD
(
" ## createNewSessionJni(): init"
);
sessionResult
=
olm_init_inbound_group_session
(
sessionPtr
,
(
const
uint8_t
*
)
sessionKeyPtr
,
sessionKeyLength
);
}
else
{
LOGD
(
" ## createNewSessionJni(): import"
);
sessionResult
=
olm_import_inbound_group_session
(
sessionPtr
,
(
const
uint8_t
*
)
sessionKeyPtr
,
sessionKeyLength
);
}
if
(
sessionResult
==
olm_error
())
{
...
...
@@ -110,11 +122,6 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *
env
->
ReleaseByteArrayElements
(
aSessionKeyBuffer
,
sessionKeyPtr
,
JNI_ABORT
);
}
if
(
errorMessage
)
{
env
->
ThrowNew
(
env
->
FindClass
(
"java/lang/Exception"
),
errorMessage
);
}
if
(
errorMessage
)
{
// release the allocated session
...
...
@@ -123,7 +130,6 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *
olm_clear_inbound_group_session
(
sessionPtr
);
free
(
sessionPtr
);
}
env
->
ThrowNew
(
env
->
FindClass
(
"java/lang/Exception"
),
errorMessage
);
}
...
...
@@ -326,6 +332,135 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn
return
decryptedMsgBuffer
;
}
/**
* Provides the first known index.
* An exception is thrown if the operation fails.
* @return the first known index
*/
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
firstKnownIndexJni
)(
JNIEnv
*
env
,
jobject
thiz
)
{
const
char
*
errorMessage
=
NULL
;
OlmInboundGroupSession
*
sessionPtr
=
getInboundGroupSessionInstanceId
(
env
,
thiz
);
long
returnValue
=
0
;
LOGD
(
"## firstKnownIndexJni(): inbound group session IN"
);
if
(
!
sessionPtr
)
{
LOGE
(
" ## firstKnownIndexJni(): failure - invalid inbound group session instance"
);
errorMessage
=
"invalid inbound group session instance"
;
}
else
{
returnValue
=
olm_inbound_group_session_first_known_index
(
sessionPtr
);
}
if
(
errorMessage
)
{
env
->
ThrowNew
(
env
->
FindClass
(
"java/lang/Exception"
),
errorMessage
);
}
return
returnValue
;
}
/**
* Tells if the session is verified.
* An exception is thrown if the operation fails.
* @return true if the session is verified
*/
JNIEXPORT
jboolean
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
isVerifiedJni
)(
JNIEnv
*
env
,
jobject
thiz
)
{
const
char
*
errorMessage
=
NULL
;
OlmInboundGroupSession
*
sessionPtr
=
getInboundGroupSessionInstanceId
(
env
,
thiz
);
jboolean
returnValue
=
JNI_FALSE
;
LOGD
(
"## isVerifiedJni(): inbound group session IN"
);
if
(
!
sessionPtr
)
{
LOGE
(
" ## isVerifiedJni(): failure - invalid inbound group session instance"
);
errorMessage
=
"invalid inbound group session instance"
;
}
else
{
LOGE
(
" ## isVerifiedJni(): faaa %d"
,
olm_inbound_group_session_is_verified
(
sessionPtr
));
returnValue
=
(
0
!=
olm_inbound_group_session_is_verified
(
sessionPtr
))
?
JNI_TRUE
:
JNI_FALSE
;
}
if
(
errorMessage
)
{
env
->
ThrowNew
(
env
->
FindClass
(
"java/lang/Exception"
),
errorMessage
);
}
return
returnValue
;
}
/**
* Exports the session as byte array from a message index
* An exception is thrown if the operation fails.
* @param messageIndex key used to encrypt the serialized session data
* @return the session saved as bytes array
**/
JNIEXPORT
jbyteArray
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
exportJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jlong
messageIndex
)
{
jbyteArray
exportedByteArray
=
0
;
const
char
*
errorMessage
=
NULL
;
OlmInboundGroupSession
*
sessionPtr
=
getInboundGroupSessionInstanceId
(
env
,
thiz
);
LOGD
(
"## exportJni(): inbound group session IN"
);
if
(
!
sessionPtr
)
{
LOGE
(
" ## exportJni (): failure - invalid inbound group session instance"
);
errorMessage
=
"invalid inbound group session instance"
;
}
else
{
size_t
length
=
olm_export_inbound_group_session_length
(
sessionPtr
);
LOGD
(
" ## exportJni(): length =%lu"
,
static_cast
<
long
unsigned
int
>
(
length
));
void
*
bufferPtr
=
malloc
(
length
*
sizeof
(
uint8_t
));
if
(
!
bufferPtr
)
{
LOGE
(
" ## exportJni(): failure - pickledPtr buffer OOM"
);
errorMessage
=
"pickledPtr buffer OOM"
;
}
else
{
size_t
result
=
olm_export_inbound_group_session
(
sessionPtr
,
(
uint8_t
*
)
bufferPtr
,
length
,
(
long
)
messageIndex
);
if
(
result
==
olm_error
())
{
errorMessage
=
olm_inbound_group_session_last_error
(
sessionPtr
);
LOGE
(
" ## exportJni(): failure - olm_export_inbound_group_session() Msg=%s"
,
errorMessage
);
}
else
{
LOGD
(
" ## exportJni(): success - result=%lu buffer=%.*s"
,
static_cast
<
long
unsigned
int
>
(
result
),
static_cast
<
int
>
(
length
),
static_cast
<
char
*>
(
bufferPtr
));
exportedByteArray
=
env
->
NewByteArray
(
length
);
env
->
SetByteArrayRegion
(
exportedByteArray
,
0
,
length
,
(
jbyte
*
)
bufferPtr
);
// clean before leaving
memset
(
bufferPtr
,
0
,
length
);
}
free
(
bufferPtr
);
}
}
if
(
errorMessage
)
{
env
->
ThrowNew
(
env
->
FindClass
(
"java/lang/Exception"
),
errorMessage
);
}
return
exportedByteArray
;
}
/**
* Serialize and encrypt session instance into a base64 string.<br>
...
...
android/olm-sdk/src/main/jni/olm_inbound_group_session.h
View file @
3c02c154
...
...
@@ -30,11 +30,16 @@ extern "C" {
// session creation/destruction
JNIEXPORT
void
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
releaseSessionJni
)(
JNIEnv
*
env
,
jobject
thiz
);
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
createNewSessionJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aSessionKeyBuffer
);
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
createNewSessionJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aSessionKeyBuffer
,
jboolean
isImported
);
JNIEXPORT
jbyteArray
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
sessionIdentifierJni
)(
JNIEnv
*
env
,
jobject
thiz
);
JNIEXPORT
jbyteArray
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
decryptMessageJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aEncryptedMsg
,
jobject
aDecryptIndex
);
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
firstKnownIndexJni
)(
JNIEnv
*
env
,
jobject
thiz
);
JNIEXPORT
jboolean
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
isVerifiedJni
)(
JNIEnv
*
env
,
jobject
thiz
);
JNIEXPORT
jbyteArray
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
exportJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jlong
messageIndex
);
// serialization
JNIEXPORT
jbyteArray
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
serializeJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aKey
);
JNIEXPORT
jlong
OLM_INBOUND_GROUP_SESSION_FUNC_DEF
(
deserializeJni
)(
JNIEnv
*
env
,
jobject
thiz
,
jbyteArray
aSerializedData
,
jbyteArray
aKey
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment