LCOV - code coverage report
Current view: top level - src - native.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 443 443 100.0 %
Date: 2022-08-24 00:20:53 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2020 Famedly GmbH
       2             : // SPDX-License-Identifier: AGPL-3.0-or-later
       3             : 
       4             : import 'dart:convert';
       5             : import 'dart:ffi';
       6             : import 'dart:math';
       7             : import 'dart:typed_data';
       8             : 
       9             : import 'package:ffi/ffi.dart';
      10             : 
      11             : import 'common.dart';
      12             : import 'ffi.dart';
      13             : 
      14             : typedef _ObjectLengthFunc = int Function(Pointer<NativeType>);
      15             : typedef _PickleUnpickleFunc = int Function(
      16             :     Pointer<NativeType>, Pointer<Uint8>, int, Pointer<Uint8>, int);
      17             : typedef _CalculateMacFunc = int Function(Pointer<NativeType>, Pointer<Uint8>,
      18             :     int, Pointer<Uint8>, int, Pointer<Uint8>, int);
      19             : 
      20           1 : String _readStr(
      21             :     _ObjectLengthFunc len,
      22             :     int Function(Pointer<NativeType>, Pointer<Uint8>, int) data,
      23             :     Pointer<NativeType> inst) {
      24           1 :   final l = len(inst);
      25             :   final mem = malloc.call<Uint8>(l);
      26             :   try {
      27           1 :     final dl = data(inst, mem, l);
      28           2 :     assert(dl <= l);
      29           2 :     return utf8.decode(mem.asTypedList(dl));
      30             :   } finally {
      31           1 :     malloc.free(mem);
      32             :   }
      33             : }
      34             : 
      35           1 : String _readStr2(
      36             :     _ObjectLengthFunc len,
      37             :     int Function(Pointer<NativeType>, Pointer<Uint8>, int) data,
      38             :     Pointer<NativeType> inst) {
      39           1 :   final l = len(inst);
      40             :   final mem = malloc.call<Uint8>(l);
      41             :   try {
      42           1 :     data(inst, mem, l);
      43           2 :     return utf8.decode(mem.asTypedList(l));
      44             :   } finally {
      45           1 :     malloc.free(mem);
      46             :   }
      47             : }
      48             : 
      49           1 : String _pickle(_ObjectLengthFunc len, _PickleUnpickleFunc data,
      50             :     Pointer<NativeType> inst, String key) {
      51           1 :   final units = utf8.encode(key);
      52           1 :   final outLen = len(inst);
      53           2 :   final mem = malloc.call<Uint8>(units.length + outLen);
      54           1 :   final outMem = mem.elementAt(units.length);
      55             :   try {
      56           3 :     mem.asTypedList(units.length).setAll(0, units);
      57           2 :     data(inst, mem, units.length, outMem, outLen);
      58           2 :     return utf8.decode(outMem.asTypedList(outLen));
      59             :   } finally {
      60           1 :     malloc.free(mem);
      61             :   }
      62             : }
      63             : 
      64           1 : void _unpickle(_PickleUnpickleFunc func, Pointer<NativeType> inst, String data,
      65             :     String key) {
      66           1 :   final dby = utf8.encode(data);
      67           1 :   final kby = utf8.encode(key);
      68           3 :   final mem = malloc.call<Uint8>(dby.length + kby.length);
      69           1 :   final keyMem = mem.elementAt(dby.length);
      70             :   try {
      71           3 :     mem.asTypedList(dby.length).setAll(0, dby);
      72           3 :     keyMem.asTypedList(kby.length).setAll(0, kby);
      73           3 :     func(inst, keyMem, kby.length, mem, dby.length);
      74             :   } finally {
      75           1 :     malloc.free(mem);
      76             :   }
      77             : }
      78             : 
      79           1 : String _calculateMac(_CalculateMacFunc func, Pointer<NativeType> inst,
      80             :     String input, String info) {
      81           1 :   final inputUnits = utf8.encode(input);
      82           1 :   final infoUnits = utf8.encode(info);
      83           1 :   final outMemLen = olm_sas_mac_length(inst);
      84             :   final mem =
      85           4 :       malloc.call<Uint8>(inputUnits.length + infoUnits.length + outMemLen);
      86           1 :   final infoMem = mem.elementAt(inputUnits.length);
      87           1 :   final outMem = infoMem.elementAt(infoUnits.length);
      88             :   try {
      89           3 :     mem.asTypedList(inputUnits.length).setAll(0, inputUnits);
      90           3 :     infoMem.asTypedList(infoUnits.length).setAll(0, infoUnits);
      91           3 :     func(inst, mem, inputUnits.length, infoMem, infoUnits.length, outMem,
      92             :         outMemLen);
      93           2 :     return utf8.decode(outMem.asTypedList(outMemLen));
      94             :   } finally {
      95           1 :     malloc.free(mem);
      96             :   }
      97             : }
      98             : 
      99           1 : void _fillRandom(Uint8List list) {
     100           1 :   final rng = Random.secure();
     101           5 :   list.setAll(0, Iterable.generate(list.length, (i) => rng.nextInt(256)));
     102             : }
     103             : 
     104           1 : void _createRandom(
     105             :     void Function(Pointer<NativeType>, Pointer<Uint8> random, int size) func,
     106             :     _ObjectLengthFunc len,
     107             :     Pointer<NativeType> inst) {
     108           1 :   final l = len(inst);
     109             :   final mem = malloc.call<Uint8>(l);
     110             :   try {
     111           2 :     _fillRandom(mem.asTypedList(l));
     112           1 :     func(inst, mem, l);
     113             :   } finally {
     114           1 :     malloc.free(mem);
     115             :   }
     116             : }
     117             : 
     118             : class _NativeObject {
     119             :   Pointer<Uint8> _mem;
     120             :   Pointer<NativeType>? _maybeInst;
     121           2 :   Pointer<NativeType> get _inst => _maybeInst ?? (throw UseAfterFreeError());
     122             : 
     123           1 :   _NativeObject(int Function() get_size,
     124             :       Pointer<NativeType> Function(Pointer<Uint8>) create)
     125           1 :       : _mem = malloc.call<Uint8>(get_size()) {
     126           3 :     _maybeInst = create(_mem);
     127             :   }
     128             : 
     129           1 :   void _freed() {
     130           1 :     _maybeInst = null;
     131           2 :     malloc.free(_mem);
     132             :   }
     133             : }
     134             : 
     135           1 : Future<void> init() async {
     136           1 :   olm_get_library_version; // just load the function, not calling it
     137             : }
     138             : 
     139           1 : List<int> get_library_version() {
     140             :   final mem = malloc.call<Uint8>(3);
     141             :   try {
     142           2 :     olm_get_library_version(
     143             :         mem.elementAt(0), mem.elementAt(1), mem.elementAt(2));
     144           2 :     return List<int>.from(mem.asTypedList(3));
     145             :   } finally {
     146           1 :     malloc.free(mem);
     147             :   }
     148             : }
     149             : 
     150             : class EncryptResult {
     151             :   int type;
     152             :   String body;
     153           1 :   EncryptResult._(this.type, this.body);
     154             : }
     155             : 
     156             : class DecryptResult {
     157             :   int message_index;
     158             :   String plaintext;
     159           1 :   DecryptResult._(this.message_index, this.plaintext);
     160             : }
     161             : 
     162             : class Account extends _NativeObject {
     163           4 :   Account() : super(olm_account_size, olm_account);
     164             : 
     165           1 :   void free() {
     166           2 :     olm_clear_account(_inst);
     167           1 :     _freed();
     168             :   }
     169             : 
     170           1 :   void create() {
     171           2 :     _createRandom(olm_create_account, olm_create_account_random_length, _inst);
     172             :   }
     173             : 
     174           1 :   String identity_keys() {
     175           1 :     return _readStr(
     176           1 :         olm_account_identity_keys_length, olm_account_identity_keys, _inst);
     177             :   }
     178             : 
     179           1 :   String one_time_keys() {
     180           1 :     return _readStr(
     181           1 :         olm_account_one_time_keys_length, olm_account_one_time_keys, _inst);
     182             :   }
     183             : 
     184           1 :   String fallback_key() {
     185           1 :     return _readStr(
     186           1 :         olm_account_fallback_key_length, olm_account_fallback_key, _inst);
     187             :   }
     188             : 
     189           1 :   String unpublished_fallback_key() {
     190           1 :     return _readStr(olm_account_unpublished_fallback_key_length,
     191           1 :         olm_account_unpublished_fallback_key, _inst);
     192             :   }
     193             : 
     194           1 :   String pickle(String key) {
     195           2 :     return _pickle(olm_pickle_account_length, olm_pickle_account, _inst, key);
     196             :   }
     197             : 
     198           1 :   void unpickle(String key, String data) {
     199           2 :     return _unpickle(olm_unpickle_account, _inst, data, key);
     200             :   }
     201             : 
     202           1 :   void generate_one_time_keys(int count) {
     203           1 :     _createRandom(
     204           1 :         (inst, random, size) =>
     205           2 :             olm_account_generate_one_time_keys(_inst, count, random, size),
     206           2 :         (inst) => olm_account_generate_one_time_keys_random_length(inst, count),
     207           1 :         _inst);
     208             :   }
     209             : 
     210           1 :   void generate_fallback_key() {
     211           1 :     _createRandom(olm_account_generate_fallback_key,
     212           1 :         olm_account_generate_fallback_key_random_length, _inst);
     213             :   }
     214             : 
     215           1 :   void remove_one_time_keys(Session session) {
     216           3 :     olm_remove_one_time_keys(_inst, session._inst);
     217             :   }
     218             : 
     219           1 :   void mark_keys_as_published() {
     220           2 :     olm_account_mark_keys_as_published(_inst);
     221             :   }
     222             : 
     223           1 :   int max_number_of_one_time_keys() {
     224           2 :     return olm_account_max_number_of_one_time_keys(_inst);
     225             :   }
     226             : 
     227           1 :   String sign(String message) {
     228           1 :     final units = utf8.encode(message);
     229           2 :     final outLen = olm_account_signature_length(_inst);
     230           2 :     final mem = malloc.call<Uint8>(units.length + outLen);
     231           1 :     final outMem = mem.elementAt(units.length);
     232             :     try {
     233           3 :       mem.asTypedList(units.length).setAll(0, units);
     234           3 :       olm_account_sign(_inst, mem, units.length, outMem, outLen);
     235           2 :       return utf8.decode(outMem.asTypedList(outLen));
     236             :     } finally {
     237           1 :       malloc.free(mem);
     238             :     }
     239             :   }
     240             : }
     241             : 
     242             : class Session extends _NativeObject {
     243           4 :   Session() : super(olm_session_size, olm_session);
     244             : 
     245           1 :   void free() {
     246           2 :     olm_clear_session(_inst);
     247           1 :     _freed();
     248             :   }
     249             : 
     250           1 :   String pickle(String key) {
     251           2 :     return _pickle(olm_pickle_session_length, olm_pickle_session, _inst, key);
     252             :   }
     253             : 
     254           1 :   void unpickle(String key, String data) {
     255           2 :     return _unpickle(olm_unpickle_session, _inst, data, key);
     256             :   }
     257             : 
     258           1 :   void create_outbound(
     259             :       Account account, String identity_key, String one_time_key) {
     260           1 :     final identity_key_units = utf8.encode(identity_key);
     261           1 :     final one_time_key_units = utf8.encode(one_time_key);
     262           2 :     final randomLen = olm_create_outbound_session_random_length(_inst);
     263             :     final mem = malloc.call<Uint8>(
     264           4 :         identity_key_units.length + one_time_key_units.length + randomLen);
     265           1 :     final otMem = mem.elementAt(identity_key_units.length);
     266           1 :     final rndMem = otMem.elementAt(one_time_key_units.length);
     267             :     try {
     268           3 :       mem.asTypedList(identity_key_units.length).setAll(0, identity_key_units);
     269             :       otMem
     270           2 :           .asTypedList(one_time_key_units.length)
     271           1 :           .setAll(0, one_time_key_units);
     272           2 :       _fillRandom(rndMem.asTypedList(randomLen));
     273           1 :       olm_create_outbound_session(
     274           1 :           _inst,
     275           1 :           account._inst,
     276             :           mem,
     277           1 :           identity_key_units.length,
     278             :           otMem,
     279           1 :           one_time_key_units.length,
     280             :           rndMem,
     281             :           randomLen);
     282             :     } finally {
     283           1 :       malloc.free(mem);
     284             :     }
     285             :   }
     286             : 
     287           1 :   void create_inbound(Account account, String message) {
     288           1 :     final message_units = utf8.encode(message);
     289           1 :     final mem = malloc.call<Uint8>(message_units.length);
     290             :     try {
     291           3 :       mem.asTypedList(message_units.length).setAll(0, message_units);
     292           1 :       olm_create_inbound_session(
     293           3 :           _inst, account._inst, mem, message_units.length);
     294             :     } finally {
     295           1 :       malloc.free(mem);
     296             :     }
     297             :   }
     298             : 
     299           1 :   void create_inbound_from(
     300             :       Account account, String identity_key, String one_time_key) {
     301           1 :     final identity_key_units = utf8.encode(identity_key);
     302           1 :     final one_time_key_units = utf8.encode(one_time_key);
     303             :     final mem = malloc
     304           3 :         .call<Uint8>(identity_key_units.length + one_time_key_units.length);
     305           1 :     final otMem = mem.elementAt(identity_key_units.length);
     306             :     try {
     307           3 :       mem.asTypedList(identity_key_units.length).setAll(0, identity_key_units);
     308             :       otMem
     309           2 :           .asTypedList(one_time_key_units.length)
     310           1 :           .setAll(0, one_time_key_units);
     311           3 :       olm_create_inbound_session_from(_inst, account._inst, mem,
     312           2 :           identity_key_units.length, otMem, one_time_key_units.length);
     313             :     } finally {
     314           1 :       malloc.free(mem);
     315             :     }
     316             :   }
     317             : 
     318           1 :   String session_id() {
     319           2 :     return _readStr(olm_session_id_length, olm_session_id, _inst);
     320             :   }
     321             : 
     322           1 :   bool has_received_message() {
     323           4 :     return olm_session_has_received_message(_inst) != 0;
     324             :   }
     325             : 
     326           1 :   int encrypt_message_type() {
     327           2 :     return olm_encrypt_message_type(_inst);
     328             :   }
     329             : 
     330           1 :   bool matches_inbound(String message) {
     331           1 :     final message_units = utf8.encode(message);
     332           1 :     final mem = malloc.call<Uint8>(message_units.length);
     333           3 :     mem.asTypedList(message_units.length).setAll(0, message_units);
     334             :     try {
     335           4 :       return olm_matches_inbound_session(_inst, mem, message_units.length) != 0;
     336             :     } finally {
     337           1 :       malloc.free(mem);
     338             :     }
     339             :   }
     340             : 
     341           1 :   bool matches_inbound_from(String identity_key, String message) {
     342           1 :     final identity_key_units = utf8.encode(identity_key);
     343           1 :     final message_units = utf8.encode(message);
     344             :     final mem =
     345           3 :         malloc.call<Uint8>(identity_key_units.length + message_units.length);
     346           1 :     final mem2 = mem.elementAt(identity_key_units.length);
     347           3 :     mem.asTypedList(identity_key_units.length).setAll(0, identity_key_units);
     348           3 :     mem2.asTypedList(message_units.length).setAll(0, message_units);
     349             :     try {
     350           2 :       return olm_matches_inbound_session_from(_inst, mem,
     351           2 :               identity_key_units.length, mem2, message_units.length) !=
     352             :           0;
     353             :     } finally {
     354           1 :       malloc.free(mem);
     355             :     }
     356             :   }
     357             : 
     358           1 :   EncryptResult encrypt(String plaintext) {
     359           1 :     final units = utf8.encode(plaintext);
     360           2 :     final randomLen = olm_encrypt_random_length(_inst);
     361           3 :     final outLen = olm_encrypt_message_length(_inst, units.length);
     362           3 :     final mem = malloc.call<Uint8>(units.length + randomLen + outLen);
     363           1 :     final rndMem = mem.elementAt(units.length);
     364             :     final outMem = rndMem.elementAt(randomLen);
     365             :     try {
     366           3 :       mem.asTypedList(units.length).setAll(0, units);
     367           2 :       _fillRandom(rndMem.asTypedList(randomLen));
     368           1 :       final result1 = encrypt_message_type();
     369           3 :       olm_encrypt(_inst, mem, units.length, rndMem, randomLen, outMem, outLen);
     370           2 :       final result2 = utf8.decode(outMem.asTypedList(outLen));
     371           1 :       return EncryptResult._(result1, result2);
     372             :     } finally {
     373           1 :       malloc.free(mem);
     374             :     }
     375             :   }
     376             : 
     377           1 :   String decrypt(int message_type, String message) {
     378           1 :     final units = utf8.encode(message);
     379           1 :     final mem = malloc.call<Uint8>(units.length);
     380             :     try {
     381           3 :       mem.asTypedList(units.length).setAll(0, units);
     382           1 :       int outLen = olm_decrypt_max_plaintext_length(
     383           2 :           _inst, message_type, mem, units.length);
     384           3 :       mem.asTypedList(units.length).setAll(0, units);
     385             :       final outMem = malloc.call<Uint8>(outLen);
     386             :       try {
     387             :         outLen =
     388           3 :             olm_decrypt(_inst, message_type, mem, units.length, outMem, outLen);
     389           2 :         return utf8.decode(outMem.asTypedList(outLen));
     390             :       } finally {
     391           1 :         malloc.free(outMem);
     392             :       }
     393             :     } finally {
     394           1 :       malloc.free(mem);
     395             :     }
     396             :   }
     397             : }
     398             : 
     399             : class Utility extends _NativeObject {
     400           4 :   Utility() : super(olm_utility_size, olm_utility);
     401             : 
     402           1 :   void free() {
     403           2 :     olm_clear_utility(_inst);
     404           1 :     _freed();
     405             :   }
     406             : 
     407           1 :   String sha256(String input) {
     408           3 :     return sha256_bytes(utf8.encoder.convert(input));
     409             :   }
     410             : 
     411             :   /// Not implemented for Web in upstream olm.
     412           1 :   String sha256_bytes(Uint8List input) {
     413           1 :     final mem = malloc.call<Uint8>(input.length);
     414           3 :     mem.asTypedList(input.length).setAll(0, input);
     415             :     try {
     416           2 :       return sha256_pointer(mem, input.length);
     417             :     } finally {
     418           1 :       malloc.free(mem);
     419             :     }
     420             :   }
     421             : 
     422             :   /// Available for Native only.
     423           1 :   String sha256_pointer(Pointer<Uint8> input, int size) {
     424           2 :     final outLen = olm_sha256_length(_inst);
     425             :     final outMem = malloc.call<Uint8>(outLen);
     426             :     try {
     427           2 :       olm_sha256(_inst, input, size, outMem, outLen);
     428           2 :       return utf8.decode(outMem.asTypedList(outLen));
     429             :     } finally {
     430           1 :       malloc.free(outMem);
     431             :     }
     432             :   }
     433             : 
     434           1 :   void ed25519_verify(String key, String message, String signature) {
     435           1 :     final key_units = utf8.encode(key);
     436           1 :     final message_units = utf8.encode(message);
     437           1 :     final signature_units = utf8.encode(signature);
     438             :     final mem1 = malloc.call<Uint8>(
     439           5 :         key_units.length + message_units.length + signature_units.length);
     440           1 :     final mem2 = mem1.elementAt(key_units.length);
     441           1 :     final mem3 = mem2.elementAt(message_units.length);
     442             :     try {
     443           3 :       mem1.asTypedList(key_units.length).setAll(0, key_units);
     444           3 :       mem2.asTypedList(message_units.length).setAll(0, message_units);
     445           3 :       mem3.asTypedList(signature_units.length).setAll(0, signature_units);
     446           3 :       olm_ed25519_verify(_inst, mem1, key_units.length, mem2,
     447           2 :           message_units.length, mem3, signature_units.length);
     448             :     } finally {
     449           1 :       malloc.free(mem1);
     450             :     }
     451             :   }
     452             : }
     453             : 
     454             : class InboundGroupSession extends _NativeObject {
     455           1 :   InboundGroupSession()
     456           3 :       : super(olm_inbound_group_session_size, olm_inbound_group_session);
     457             : 
     458           1 :   void free() {
     459           2 :     olm_clear_inbound_group_session(_inst);
     460           1 :     _freed();
     461             :   }
     462             : 
     463           1 :   String pickle(String key) {
     464           1 :     return _pickle(olm_pickle_inbound_group_session_length,
     465           1 :         olm_pickle_inbound_group_session, _inst, key);
     466             :   }
     467             : 
     468           1 :   void unpickle(String key, String data) {
     469           2 :     return _unpickle(olm_unpickle_inbound_group_session, _inst, data, key);
     470             :   }
     471             : 
     472           1 :   void create(String session_key) {
     473           1 :     final units = utf8.encode(session_key);
     474           1 :     final mem = malloc.call<Uint8>(units.length);
     475             :     try {
     476           3 :       mem.asTypedList(units.length).setAll(0, units);
     477           3 :       olm_init_inbound_group_session(_inst, mem, units.length);
     478             :     } finally {
     479           1 :       malloc.free(mem);
     480             :     }
     481             :   }
     482             : 
     483           1 :   void import_session(String session_key) {
     484           1 :     final units = utf8.encode(session_key);
     485           1 :     final mem = malloc.call<Uint8>(units.length);
     486             :     try {
     487           3 :       mem.asTypedList(units.length).setAll(0, units);
     488           3 :       olm_import_inbound_group_session(_inst, mem, units.length);
     489             :     } finally {
     490           1 :       malloc.free(mem);
     491             :     }
     492             :   }
     493             : 
     494           1 :   DecryptResult decrypt(String message) {
     495           1 :     final units = utf8.encode(message);
     496           1 :     final mem = malloc.call<Uint8>(units.length);
     497             :     try {
     498           3 :       mem.asTypedList(units.length).setAll(0, units);
     499             :       int outLen =
     500           3 :           olm_group_decrypt_max_plaintext_length(_inst, mem, units.length);
     501           3 :       mem.asTypedList(units.length).setAll(0, units);
     502           1 :       final outMem = malloc.call<Uint8>(outLen + 4);
     503           1 :       final outMem2 = outMem.elementAt(outLen).cast<Uint32>();
     504             :       try {
     505           1 :         outLen = olm_group_decrypt(
     506           2 :             _inst, mem, units.length, outMem, outLen, outMem2);
     507           1 :         return DecryptResult._(
     508           3 :             outMem2.value, utf8.decode(outMem.asTypedList(outLen)));
     509             :       } finally {
     510           1 :         malloc.free(outMem);
     511             :       }
     512             :     } finally {
     513           1 :       malloc.free(mem);
     514             :     }
     515             :   }
     516             : 
     517           1 :   String session_id() {
     518           1 :     return _readStr(olm_inbound_group_session_id_length,
     519           1 :         olm_inbound_group_session_id, _inst);
     520             :   }
     521             : 
     522           1 :   int first_known_index() {
     523           3 :     return olm_inbound_group_session_first_known_index(_inst);
     524             :   }
     525             : 
     526           1 :   String export_session(int message_index) {
     527           1 :     return _readStr(
     528             :         olm_export_inbound_group_session_length,
     529           1 :         (inst, mem, len) =>
     530           1 :             olm_export_inbound_group_session(inst, mem, len, message_index),
     531           1 :         _inst);
     532             :   }
     533             : }
     534             : 
     535             : class OutboundGroupSession extends _NativeObject {
     536           1 :   OutboundGroupSession()
     537           3 :       : super(olm_outbound_group_session_size, olm_outbound_group_session);
     538             : 
     539           1 :   void free() {
     540           2 :     olm_clear_outbound_group_session(_inst);
     541           1 :     _freed();
     542             :   }
     543             : 
     544           1 :   String pickle(String key) {
     545           1 :     return _pickle(olm_pickle_outbound_group_session_length,
     546           1 :         olm_pickle_outbound_group_session, _inst, key);
     547             :   }
     548             : 
     549           1 :   void unpickle(String key, String data) {
     550           2 :     return _unpickle(olm_unpickle_outbound_group_session, _inst, data, key);
     551             :   }
     552             : 
     553           1 :   void create() {
     554           1 :     _createRandom(olm_init_outbound_group_session,
     555           1 :         olm_init_outbound_group_session_random_length, _inst);
     556             :   }
     557             : 
     558           1 :   String encrypt(String plaintext) {
     559           1 :     final units = utf8.encode(plaintext);
     560           3 :     final outLen = olm_group_encrypt_message_length(_inst, units.length);
     561           2 :     final mem = malloc.call<Uint8>(units.length + outLen);
     562           1 :     final outMem = mem.elementAt(units.length);
     563             :     try {
     564           3 :       mem.asTypedList(units.length).setAll(0, units);
     565           3 :       olm_group_encrypt(_inst, mem, units.length, outMem, outLen);
     566           2 :       return utf8.decode(outMem.asTypedList(outLen));
     567             :     } finally {
     568           1 :       malloc.free(mem);
     569             :     }
     570             :   }
     571             : 
     572           1 :   String session_id() {
     573           1 :     return _readStr(olm_outbound_group_session_id_length,
     574           1 :         olm_outbound_group_session_id, _inst);
     575             :   }
     576             : 
     577           1 :   int message_index() {
     578           3 :     return olm_outbound_group_session_message_index(_inst);
     579             :   }
     580             : 
     581           1 :   String session_key() {
     582           1 :     return _readStr(olm_outbound_group_session_key_length,
     583           1 :         olm_outbound_group_session_key, _inst);
     584             :   }
     585             : }
     586             : 
     587             : class SAS extends _NativeObject {
     588           4 :   SAS() : super(olm_sas_size, olm_sas) {
     589           2 :     _createRandom(olm_create_sas, olm_create_sas_random_length, _inst);
     590             :   }
     591             : 
     592           1 :   void free() {
     593           2 :     olm_clear_sas(_inst);
     594           1 :     _freed();
     595             :   }
     596             : 
     597           1 :   String get_pubkey() {
     598           2 :     return _readStr2(olm_sas_pubkey_length, olm_sas_get_pubkey, _inst);
     599             :   }
     600             : 
     601           1 :   void set_their_key(String their_key) {
     602           1 :     final units = utf8.encode(their_key);
     603           1 :     final mem = malloc.call<Uint8>(units.length);
     604             :     try {
     605           3 :       mem.asTypedList(units.length).setAll(0, units);
     606           3 :       olm_sas_set_their_key(_inst, mem, units.length);
     607             :     } finally {
     608           1 :       malloc.free(mem);
     609             :     }
     610             :   }
     611             : 
     612           1 :   Uint8List generate_bytes(String info, int length) {
     613           1 :     final units = utf8.encode(info);
     614           2 :     final mem = malloc.call<Uint8>(units.length + length);
     615           1 :     final outMem = mem.elementAt(units.length);
     616             :     try {
     617           3 :       mem.asTypedList(units.length).setAll(0, units);
     618           3 :       olm_sas_generate_bytes(_inst, mem, units.length, outMem, length);
     619           2 :       return Uint8List.fromList(outMem.asTypedList(length));
     620             :     } finally {
     621           1 :       malloc.free(mem);
     622             :     }
     623             :   }
     624             : 
     625           1 :   String calculate_mac(String input, String info) {
     626           2 :     return _calculateMac(olm_sas_calculate_mac, _inst, input, info);
     627             :   }
     628             : 
     629           1 :   String calculate_mac_long_kdf(String input, String info) {
     630           2 :     return _calculateMac(olm_sas_calculate_mac_long_kdf, _inst, input, info);
     631             :   }
     632             : }
     633             : 
     634             : class PkEncryptResult {
     635             :   String ciphertext;
     636             :   String mac;
     637             :   String ephemeral;
     638           1 :   PkEncryptResult._(this.ciphertext, this.mac, this.ephemeral);
     639             : }
     640             : 
     641             : class PkEncryption extends _NativeObject {
     642           4 :   PkEncryption() : super(olm_pk_encryption_size, olm_pk_encryption);
     643             : 
     644           1 :   void free() {
     645           2 :     olm_clear_pk_encryption(_inst);
     646           1 :     _freed();
     647             :   }
     648             : 
     649           1 :   void set_recipient_key(String key) {
     650           1 :     final units = utf8.encode(key);
     651           1 :     final mem = malloc.call<Uint8>(units.length);
     652             :     try {
     653           3 :       mem.asTypedList(units.length).setAll(0, units);
     654           3 :       olm_pk_encryption_set_recipient_key(_inst, mem, units.length);
     655             :     } finally {
     656           1 :       malloc.free(mem);
     657             :     }
     658             :   }
     659             : 
     660           1 :   PkEncryptResult encrypt(String plaintext) {
     661           1 :     final units = utf8.encode(plaintext);
     662           2 :     final rndLen = olm_pk_encrypt_random_length(_inst);
     663           3 :     final outLen = olm_pk_ciphertext_length(_inst, units.length);
     664           2 :     final macLen = olm_pk_mac_length(_inst);
     665           2 :     final ephLen = olm_pk_key_length();
     666             :     final mem =
     667           5 :         malloc.call<Uint8>(units.length + rndLen + outLen + macLen + ephLen);
     668           1 :     final rndMem = mem.elementAt(units.length);
     669             :     final outMem = rndMem.elementAt(rndLen);
     670             :     final macMem = outMem.elementAt(outLen);
     671             :     final ephMem = macMem.elementAt(macLen);
     672             :     try {
     673           3 :       mem.asTypedList(units.length).setAll(0, units);
     674           2 :       _fillRandom(rndMem.asTypedList(rndLen));
     675           3 :       olm_pk_encrypt(_inst, mem, units.length, outMem, outLen, macMem, macLen,
     676             :           ephMem, ephLen, rndMem, rndLen);
     677           1 :       return PkEncryptResult._(
     678           2 :           utf8.decode(outMem.asTypedList(outLen)),
     679           2 :           utf8.decode(macMem.asTypedList(macLen)),
     680           2 :           utf8.decode(ephMem.asTypedList(ephLen)));
     681             :     } finally {
     682           1 :       malloc.free(mem);
     683             :     }
     684             :   }
     685             : }
     686             : 
     687             : class PkDecryption extends _NativeObject {
     688           4 :   PkDecryption() : super(olm_pk_decryption_size, olm_pk_decryption);
     689             : 
     690           1 :   void free() {
     691           2 :     olm_clear_pk_decryption(_inst);
     692           1 :     _freed();
     693             :   }
     694             : 
     695           1 :   String init_with_private_key(Uint8List private_key) {
     696           2 :     final outLen = olm_pk_key_length();
     697           2 :     final mem = malloc.call<Uint8>(private_key.length + outLen);
     698           1 :     final outMem = mem.elementAt(private_key.length);
     699             :     try {
     700           3 :       mem.asTypedList(private_key.length).setAll(0, private_key);
     701           3 :       olm_pk_key_from_private(_inst, outMem, outLen, mem, private_key.length);
     702           2 :       return utf8.decode(outMem.asTypedList(outLen));
     703             :     } finally {
     704           1 :       malloc.free(mem);
     705             :     }
     706             :   }
     707             : 
     708           1 :   String generate_key() {
     709           2 :     final len = olm_pk_private_key_length();
     710           2 :     final outLen = olm_pk_key_length();
     711           1 :     final mem = malloc.call<Uint8>(len + outLen);
     712             :     final outMem = mem.elementAt(len);
     713             :     try {
     714           2 :       _fillRandom(mem.asTypedList(len));
     715           2 :       olm_pk_key_from_private(_inst, outMem, outLen, mem, len);
     716           2 :       return utf8.decode(outMem.asTypedList(outLen));
     717             :     } finally {
     718           1 :       malloc.free(mem);
     719             :     }
     720             :   }
     721             : 
     722           1 :   Uint8List get_private_key() {
     723           2 :     final len = olm_pk_private_key_length();
     724             :     final mem = malloc.call<Uint8>(len);
     725             :     try {
     726           2 :       olm_pk_get_private_key(_inst, mem, len);
     727           2 :       return Uint8List.fromList(mem.asTypedList(len));
     728             :     } finally {
     729           1 :       malloc.free(mem);
     730             :     }
     731             :   }
     732             : 
     733           1 :   String pickle(String key) {
     734           1 :     return _pickle(
     735           1 :         olm_pickle_pk_decryption_length, olm_pickle_pk_decryption, _inst, key);
     736             :   }
     737             : 
     738           1 :   String unpickle(String key, String data) {
     739           1 :     final dby = utf8.encode(data);
     740           1 :     final kby = utf8.encode(key);
     741           2 :     final outLen = olm_pk_key_length();
     742           4 :     final mem = malloc.call<Uint8>(dby.length + kby.length + outLen);
     743           1 :     final keyMem = mem.elementAt(dby.length);
     744           1 :     final outMem = keyMem.elementAt(kby.length);
     745             :     try {
     746           3 :       mem.asTypedList(dby.length).setAll(0, dby);
     747           3 :       keyMem.asTypedList(kby.length).setAll(0, kby);
     748           1 :       olm_unpickle_pk_decryption(
     749           3 :           _inst, keyMem, kby.length, mem, dby.length, outMem, outLen);
     750           2 :       return utf8.decode(outMem.asTypedList(outLen));
     751             :     } finally {
     752           1 :       malloc.free(mem);
     753             :     }
     754             :   }
     755             : 
     756           1 :   String decrypt(String ephemeral_key, String mac, String ciphertext) {
     757           1 :     final ephUnits = utf8.encode(ephemeral_key);
     758           1 :     final macUnits = utf8.encode(mac);
     759           1 :     final ciphertextUnits = utf8.encode(ciphertext);
     760             : 
     761             :     int plaintextLen =
     762           3 :         olm_pk_max_plaintext_length(_inst, ciphertextUnits.length);
     763           2 :     final mem = malloc.call<Uint8>(ephUnits.length +
     764           2 :         macUnits.length +
     765           2 :         ciphertextUnits.length +
     766             :         plaintextLen);
     767           1 :     final macMem = mem.elementAt(ephUnits.length);
     768           1 :     final ciphertextMem = macMem.elementAt(macUnits.length);
     769           1 :     final plaintextMem = ciphertextMem.elementAt(ciphertextUnits.length);
     770             :     try {
     771           3 :       mem.asTypedList(ephUnits.length).setAll(0, ephUnits);
     772           3 :       macMem.asTypedList(macUnits.length).setAll(0, macUnits);
     773             :       ciphertextMem
     774           2 :           .asTypedList(ciphertextUnits.length)
     775           1 :           .setAll(0, ciphertextUnits);
     776           1 :       plaintextLen = olm_pk_decrypt(
     777           1 :           _inst,
     778             :           mem,
     779           1 :           ephUnits.length,
     780             :           macMem,
     781           1 :           macUnits.length,
     782             :           ciphertextMem,
     783           1 :           ciphertextUnits.length,
     784             :           plaintextMem,
     785             :           plaintextLen);
     786           2 :       return utf8.decode(plaintextMem.asTypedList(plaintextLen));
     787             :     } finally {
     788           1 :       malloc.free(mem);
     789             :     }
     790             :   }
     791             : }
     792             : 
     793             : class PkSigning extends _NativeObject {
     794           4 :   PkSigning() : super(olm_pk_signing_size, olm_pk_signing);
     795             : 
     796           1 :   void free() {
     797           2 :     olm_clear_pk_signing(_inst);
     798           1 :     _freed();
     799             :   }
     800             : 
     801           1 :   String init_with_seed(Uint8List seed) {
     802           2 :     final outLen = olm_pk_signing_public_key_length();
     803           2 :     final mem = malloc.call<Uint8>(seed.length + outLen);
     804           1 :     final outMem = mem.elementAt(seed.length);
     805             :     try {
     806           3 :       mem.asTypedList(seed.length).setAll(0, seed);
     807           3 :       olm_pk_signing_key_from_seed(_inst, outMem, outLen, mem, seed.length);
     808           2 :       return utf8.decode(outMem.asTypedList(outLen));
     809             :     } finally {
     810           1 :       malloc.free(mem);
     811             :     }
     812             :   }
     813             : 
     814           1 :   Uint8List generate_seed() {
     815           3 :     final result = Uint8List(olm_pk_signing_seed_length());
     816           1 :     _fillRandom(result);
     817             :     return result;
     818             :   }
     819             : 
     820           1 :   String sign(String message) {
     821           1 :     final units = utf8.encode(message);
     822           2 :     final outLen = olm_pk_signature_length();
     823           2 :     final mem = malloc.call<Uint8>(units.length + outLen);
     824           1 :     final outMem = mem.elementAt(units.length);
     825             :     try {
     826           3 :       mem.asTypedList(units.length).setAll(0, units);
     827           3 :       olm_pk_sign(_inst, mem, units.length, outMem, outLen);
     828           2 :       return utf8.decode(outMem.asTypedList(outLen));
     829             :     } finally {
     830           1 :       malloc.free(mem);
     831             :     }
     832             :   }
     833             : }

Generated by: LCOV version 1.16