1- /* global Olm */
2-
31import { safeJsonParse as _safeJsonParse } from '@jitsi/js-utils/json' ;
42import { getLogger } from '@jitsi/logger' ;
53import base64js from 'base64-js' ;
64import { isEqual } from 'lodash-es' ;
75import { v4 as uuidv4 } from 'uuid' ;
86
7+ import JitsiConference from '../../JitsiConference' ;
98import * as JitsiConferenceEvents from '../../JitsiConferenceEvents' ;
9+ import JitsiParticipant from '../../JitsiParticipant' ;
1010import Deferred from '../util/Deferred' ;
1111import Listenable from '../util/Listenable' ;
1212import { FEATURE_E2EE , JITSI_MEET_MUC_TYPE } from '../xmpp/xmpp' ;
1313
1414import { E2EEErrors } from './E2EEErrors' ;
1515import { generateSas } from './SAS' ;
1616
17+ interface IOlmAccount {
18+ create : ( ) => void ;
19+ free : ( ) => void ;
20+ generate_one_time_keys : ( count : number ) => void ;
21+ identity_keys : ( ) => string ;
22+ mark_keys_as_published : ( ) => void ;
23+ one_time_keys : ( ) => string ;
24+ remove_one_time_keys : ( session : IOlmSession ) => void ;
25+ }
26+
27+ interface IOlmSession {
28+ create_inbound : ( account : IOlmAccount , ciphertext : string ) => void ;
29+ create_outbound : ( account : IOlmAccount , idKey : string , otKey : string ) => void ;
30+ decrypt : ( type : number , ciphertext : string ) => string ;
31+ encrypt : ( plaintext : string ) => { body : string ; type : number ; } ;
32+ free : ( ) => void ;
33+ }
34+
35+ interface IOlmSAS {
36+ calculate_mac : ( message : string , info : string ) => string ;
37+ free : ( ) => void ;
38+ generate_bytes : ( info : string , length : number ) => Uint8Array ;
39+ get_pubkey : ( ) => string ;
40+ is_their_key_set : ( ) => boolean ;
41+ set_their_key : ( key : string ) => void ;
42+ }
43+
44+ interface IOlmIdKeys {
45+ curve25519 : string ;
46+ ed25519 : string ;
47+ }
48+
49+ interface IDSasVerificationData {
50+ isInitiator ?: boolean ;
51+ keySent ?: boolean ;
52+ sas : IOlmSAS ;
53+ sasCommitment ?: string ;
54+ sasMacSent ?: boolean ;
55+ startContent ?: any ;
56+ transactionId : string ;
57+ }
58+
59+ interface IOlmData {
60+ ed25519 ?: string ;
61+ lastKey ?: Uint8Array | boolean ;
62+ pendingSessionUuid ?: string ;
63+ sasVerification ?: IDSasVerificationData ;
64+ session ?: IOlmSession ;
65+ }
66+
67+ interface IKeyInfo {
68+ key ?: string | boolean ;
69+ keyIndex ?: number ;
70+ }
71+
1772const logger = getLogger ( 'modules/e2ee/OlmAdapter' ) ;
1873
1974const REQ_TIMEOUT = 5 * 1000 ;
@@ -65,10 +120,23 @@ const OlmAdapterEvents = {
65120 * MUC private messages.
66121 */
67122export class OlmAdapter extends Listenable {
123+
124+ static events : typeof OlmAdapterEvents ;
125+
126+ private _conf : JitsiConference ;
127+ private _init : Deferred < void > ;
128+ private _mediaKey : Optional < Uint8Array | boolean > ;
129+ private _mediaKeyIndex : number ;
130+ private _reqs : Map < string , Deferred < void > > ;
131+ private _sessionInitialization : Optional < Deferred < void > > ;
132+ private _olmAccount : Optional < IOlmAccount > ;
133+ private _idKeys : Optional < IOlmIdKeys > ;
134+
135+
68136 /**
69137 * Creates an adapter instance for the given conference.
70138 */
71- constructor ( conference ) {
139+ constructor ( conference : JitsiConference ) {
72140 super ( ) ;
73141
74142 this . _conf = conference ;
@@ -103,7 +171,7 @@ export class OlmAdapter extends Listenable {
103171 /**
104172 * Starts new olm sessions with every other participant that has the participantId "smaller" the localParticipantId.
105173 */
106- async initSessions ( ) {
174+ async initSessions ( ) : Promise < void > {
107175 if ( this . _sessionInitialization ) {
108176 throw new Error ( 'OlmAdapter initSessions called multiple times' ) ;
109177 } else {
@@ -134,7 +202,7 @@ export class OlmAdapter extends Listenable {
134202 *
135203 * @returns {boolean }
136204 */
137- static isSupported ( ) {
205+ static isSupported ( ) : boolean {
138206 return typeof window . Olm !== 'undefined' ;
139207 }
140208
@@ -143,9 +211,9 @@ export class OlmAdapter extends Listenable {
143211 * by sending a key-info message.
144212 *
145213 * @param {Uint8Array|boolean } key - The new key.
146- * @retrns {Promise<Number>}
214+ * @returns {Promise<Number> }
147215 */
148- async updateKey ( key ) {
216+ async updateKey ( key : Optional < Uint8Array | boolean > ) : Promise < number > {
149217 // Store it locally for new sessions.
150218 this . _mediaKey = key ;
151219 this . _mediaKeyIndex ++ ;
@@ -200,7 +268,7 @@ export class OlmAdapter extends Listenable {
200268 * @param {Uint8Array|boolean } key - The new key.
201269 * @returns {number }
202270 */
203- updateCurrentMediaKey ( key ) {
271+ updateCurrentMediaKey ( key : Uint8Array | boolean ) : number {
204272 this . _mediaKey = key ;
205273
206274 return this . _mediaKeyIndex ;
@@ -210,7 +278,7 @@ export class OlmAdapter extends Listenable {
210278 * Frees the olmData session for the given participant.
211279 *
212280 */
213- clearParticipantSession ( participant ) {
281+ clearParticipantSession ( participant : JitsiParticipant ) : void {
214282 const olmData = this . _getParticipantOlmData ( participant ) ;
215283
216284 if ( olmData . session ) {
@@ -223,7 +291,7 @@ export class OlmAdapter extends Listenable {
223291 * Frees the olmData sessions for all participants.
224292 *
225293 */
226- clearAllParticipantsSessions ( ) {
294+ clearAllParticipantsSessions ( ) : void {
227295 for ( const participant of this . _conf . getParticipants ( ) ) {
228296 this . clearParticipantSession ( participant ) ;
229297 }
@@ -233,7 +301,7 @@ export class OlmAdapter extends Listenable {
233301 * Sends sacMac if channel verification waas successful.
234302 *
235303 */
236- markParticipantVerified ( participant , isVerified ) {
304+ markParticipantVerified ( participant : JitsiParticipant , isVerified : boolean ) : void {
237305 const olmData = this . _getParticipantOlmData ( participant ) ;
238306
239307 const pId = participant . getId ( ) ;
@@ -277,7 +345,7 @@ export class OlmAdapter extends Listenable {
277345 * @returns {Promise<void> }
278346 * @private
279347 */
280- async _bootstrapOlm ( ) {
348+ async _bootstrapOlm ( ) : Promise < void > {
281349 logger . debug ( 'Initializing Olm...' ) ;
282350
283351 try {
@@ -325,7 +393,7 @@ export class OlmAdapter extends Listenable {
325393 * @returns {Promise<void> }
326394 * @private
327395 */
328- startVerification ( participant ) {
396+ startVerification ( participant : JitsiParticipant ) : void {
329397 const pId = participant . getId ( ) ;
330398 const olmData = this . _getParticipantOlmData ( participant ) ;
331399
@@ -368,7 +436,7 @@ export class OlmAdapter extends Listenable {
368436 * Publishes our own Olmn id key in presence.
369437 * @private
370438 */
371- _onIdKeysReady ( idKeys ) {
439+ _onIdKeysReady ( idKeys : IOlmIdKeys ) : void {
372440 logger . debug ( `Olm id key ready: ${ idKeys } ` ) ;
373441
374442 // Publish it in presence.
@@ -385,7 +453,7 @@ export class OlmAdapter extends Listenable {
385453 * Event posted when the E2EE signalling channel has been established with the given participant.
386454 * @private
387455 */
388- _onParticipantE2EEChannelReady ( id ) {
456+ _onParticipantE2EEChannelReady ( id : string ) : void {
389457 logger . debug ( `E2EE channel with participant ${ id } is ready` ) ;
390458 }
391459
@@ -396,11 +464,11 @@ export class OlmAdapter extends Listenable {
396464 * @returns {string } - The encrypted text with the key information.
397465 * @private
398466 */
399- _encryptKeyInfo ( session ) {
400- const keyInfo = { } ;
467+ _encryptKeyInfo ( session : IOlmSession ) : { body : string ; type : number ; } {
468+ const keyInfo : IKeyInfo = { } ;
401469
402470 if ( this . _mediaKey !== undefined ) {
403- keyInfo . key = this . _mediaKey ? base64js . fromByteArray ( this . _mediaKey ) : false ;
471+ keyInfo . key = ( typeof this . _mediaKey === 'boolean' ) ? this . _mediaKey : base64js . fromByteArray ( this . _mediaKey ) ;
404472 keyInfo . keyIndex = this . _mediaKeyIndex ;
405473 }
406474
@@ -414,7 +482,7 @@ export class OlmAdapter extends Listenable {
414482 * @returns {Object }
415483 * @private
416484 */
417- _getParticipantOlmData ( participant ) {
485+ _getParticipantOlmData ( participant : JitsiParticipant ) : IOlmData {
418486 participant [ kOlmData ] = participant [ kOlmData ] || { } ;
419487
420488 return participant [ kOlmData ] ;
@@ -425,7 +493,7 @@ export class OlmAdapter extends Listenable {
425493 *
426494 * @private
427495 */
428- async _onConferenceLeft ( ) {
496+ async _onConferenceLeft ( ) : Promise < void > {
429497 logger . debug ( 'Conference left' ) ;
430498
431499 await this . _init ;
@@ -446,7 +514,7 @@ export class OlmAdapter extends Listenable {
446514 *
447515 * @private
448516 */
449- async _onEndpointMessageReceived ( participant , payload ) {
517+ async _onEndpointMessageReceived ( participant : JitsiParticipant , payload : any ) : Promise < void > {
450518 if ( payload [ JITSI_MEET_MUC_TYPE ] !== OLM_MESSAGE_TYPE ) {
451519 return ;
452520 }
@@ -524,7 +592,7 @@ export class OlmAdapter extends Listenable {
524592 const json = safeJsonParse ( data ) ;
525593
526594 if ( json . key ) {
527- const key = base64js . toByteArray ( json . key ) ;
595+ const key = typeof json . key === 'string' ? base64js . toByteArray ( json . key ) : json . key ;
528596 const keyIndex = json . keyIndex ;
529597
530598 olmData . lastKey = key ;
@@ -549,11 +617,11 @@ export class OlmAdapter extends Listenable {
549617 const json = safeJsonParse ( data ) ;
550618
551619 if ( json . key !== undefined && json . keyIndex !== undefined ) {
552- const key = json . key ? base64js . toByteArray ( json . key ) : false ;
620+ const key = json . key && typeof json . key === 'string' ? base64js . toByteArray ( json . key ) : json . key ;
553621 const keyIndex = json . keyIndex ;
554622
555623 if ( ! isEqual ( olmData . lastKey , key ) ) {
556- olmData . lastKey = key ;
624+ olmData . lastKey = key as boolean | Uint8Array ;
557625 this . eventEmitter . emit ( OlmAdapterEvents . PARTICIPANT_KEY_UPDATED , pId , key , keyIndex ) ;
558626 }
559627
@@ -585,11 +653,11 @@ export class OlmAdapter extends Listenable {
585653 const json = safeJsonParse ( data ) ;
586654
587655 if ( json . key !== undefined && json . keyIndex !== undefined ) {
588- const key = json . key ? base64js . toByteArray ( json . key ) : false ;
656+ const key = json . key && typeof json . key === 'string' ? base64js . toByteArray ( json . key ) : json . key ;
589657 const keyIndex = json . keyIndex ;
590658
591659 if ( ! isEqual ( olmData . lastKey , key ) ) {
592- olmData . lastKey = key ;
660+ olmData . lastKey = key as boolean | Uint8Array ;
593661 this . eventEmitter . emit ( OlmAdapterEvents . PARTICIPANT_KEY_UPDATED , pId , key , keyIndex ) ;
594662 }
595663 }
@@ -748,7 +816,7 @@ export class OlmAdapter extends Listenable {
748816 pId ,
749817 false ,
750818 E2EEErrors . E2EE_SAS_COMMITMENT_MISMATCHED ) ;
751- olmData . sasVerification . free ( ) ;
819+ olmData . sasVerification . sas . free ( ) ;
752820
753821 return ;
754822 }
@@ -874,7 +942,7 @@ export class OlmAdapter extends Listenable {
874942 *
875943 * @private
876944 */
877- _onParticipantLeft ( id , participant ) {
945+ _onParticipantLeft ( id : string , participant : JitsiParticipant ) : void {
878946 logger . debug ( `Participant ${ id } left` ) ;
879947
880948 this . clearParticipantSession ( participant ) ;
@@ -889,7 +957,7 @@ export class OlmAdapter extends Listenable {
889957 * @param {* } newValue - The property's new value.
890958 * @private
891959 */
892- async _onParticipantPropertyChanged ( participant , name , oldValue , newValue ) {
960+ async _onParticipantPropertyChanged ( participant : JitsiParticipant , name : string , oldValue : any , newValue : any ) : Promise < void > {
893961 const participantId = participant . getId ( ) ;
894962 const olmData = this . _getParticipantOlmData ( participant ) ;
895963
@@ -945,7 +1013,7 @@ export class OlmAdapter extends Listenable {
9451013 * @param {string } error - The error message.
9461014 * @returns {void }
9471015 */
948- _sendError ( participant , error ) {
1016+ _sendError ( participant : JitsiParticipant , error : string ) : void {
9491017 const pId = participant . getId ( ) ;
9501018 const err = {
9511019 [ JITSI_MEET_MUC_TYPE ] : OLM_MESSAGE_TYPE ,
@@ -968,7 +1036,7 @@ export class OlmAdapter extends Listenable {
9681036 * @param {object } data - The data that will be sent to the target participant.
9691037 * @param {string } participantId - ID of the target participant.
9701038 */
971- _sendMessage ( data , participantId ) {
1039+ _sendMessage ( data : any , participantId : string ) : void {
9721040 this . _conf . sendMessage ( data , participantId ) ;
9731041 }
9741042
@@ -979,7 +1047,7 @@ export class OlmAdapter extends Listenable {
9791047 * @returns {Promise } - The promise will be resolved when the session-ack is received.
9801048 * @private
9811049 */
982- _sendSessionInit ( participant ) {
1050+ _sendSessionInit ( participant : JitsiParticipant ) : Deferred < any > | Promise < void > {
9831051 const pId = participant . getId ( ) ;
9841052 const olmData = this . _getParticipantOlmData ( participant ) ;
9851053
@@ -1043,7 +1111,7 @@ export class OlmAdapter extends Listenable {
10431111 * The second phase of the verification process, the Key verification phase
10441112 https://spec.matrix.org/latest/client-server-api/#short-authentication-string-sas-verification
10451113 */
1046- _sendSasMac ( participant ) {
1114+ _sendSasMac ( participant : JitsiParticipant ) : void {
10471115 const pId = participant . getId ( ) ;
10481116 const olmData = this . _getParticipantOlmData ( participant ) ;
10491117 const { sas, transactionId } = olmData . sasVerification ;
@@ -1083,7 +1151,7 @@ export class OlmAdapter extends Listenable {
10831151 /**
10841152 * Computes the commitment.
10851153 */
1086- _computeCommitment ( pubKey , data ) {
1154+ _computeCommitment ( pubKey : string , data : any ) : string {
10871155 const olmUtil = new Olm . Utility ( ) ;
10881156 const commitment = olmUtil . sha256 ( pubKey + JSON . stringify ( data ) ) ;
10891157
@@ -1099,7 +1167,7 @@ export class OlmAdapter extends Listenable {
10991167 * @param {string } data - The data that needs to be parsed.
11001168 * @returns {object } - Parsed data or empty object in case of failure.
11011169 */
1102- function safeJsonParse ( data ) {
1170+ function safeJsonParse ( data : string ) : IKeyInfo {
11031171 try {
11041172 return _safeJsonParse ( data ) ;
11051173 } catch ( e ) {
0 commit comments