LCOV - code coverage report
Current view: top level - lib/src/utils/crypto - native.dart (source / functions) Hit Total Coverage
Test: merged.info Lines: 48 52 92.3 %
Date: 2024-07-12 20:20:16 Functions: 0 0 -

          Line data    Source code
       1             : // ignore_for_file: deprecated_member_use
       2             : // ignoring the elementAt deprecation because this would make the SDK
       3             : // incompatible with older flutter versions than 3.19.0 or dart 3.3.0
       4             : 
       5             : import 'dart:async';
       6             : import 'dart:ffi';
       7             : import 'dart:typed_data';
       8             : 
       9             : import 'package:ffi/ffi.dart';
      10             : 
      11             : import 'package:matrix/src/utils/crypto/ffi.dart';
      12             : 
      13             : abstract class Hash {
      14           4 :   Hash._(this.ptr);
      15             :   Pointer<NativeType> ptr;
      16             : 
      17           2 :   FutureOr<Uint8List> call(Uint8List data) {
      18           6 :     final outSize = EVP_MD_size(ptr);
      19           4 :     final mem = malloc.call<Uint8>(outSize + data.length);
      20           2 :     final dataMem = mem.elementAt(outSize);
      21             :     try {
      22           6 :       dataMem.asTypedList(data.length).setAll(0, data);
      23          12 :       EVP_Digest(dataMem, data.length, mem, nullptr, ptr, nullptr);
      24           4 :       return Uint8List.fromList(mem.asTypedList(outSize));
      25             :     } finally {
      26           2 :       malloc.free(mem);
      27             :     }
      28             :   }
      29             : }
      30             : 
      31           0 : final Hash sha1 = _Sha1();
      32           6 : final Hash sha256 = _Sha256();
      33           6 : final Hash sha512 = _Sha512();
      34             : 
      35             : class _Sha1 extends Hash {
      36           0 :   _Sha1() : super._(EVP_sha1());
      37             : }
      38             : 
      39             : class _Sha256 extends Hash {
      40           8 :   _Sha256() : super._(EVP_sha256());
      41             : }
      42             : 
      43             : class _Sha512 extends Hash {
      44           8 :   _Sha512() : super._(EVP_sha512());
      45             : }
      46             : 
      47             : abstract class Cipher {
      48           9 :   Cipher._();
      49             :   Pointer<NativeType> getAlg(int keysize);
      50           9 :   FutureOr<Uint8List> encrypt(Uint8List input, Uint8List key, Uint8List iv) {
      51          27 :     final alg = getAlg(key.length * 8);
      52             :     final mem = malloc
      53          54 :         .call<Uint8>(sizeOf<IntPtr>() + key.length + iv.length + input.length);
      54           9 :     final lenMem = mem.cast<IntPtr>();
      55           9 :     final keyMem = mem.elementAt(sizeOf<IntPtr>());
      56          18 :     final ivMem = keyMem.elementAt(key.length);
      57          18 :     final dataMem = ivMem.elementAt(iv.length);
      58             :     try {
      59          27 :       keyMem.asTypedList(key.length).setAll(0, key);
      60          27 :       ivMem.asTypedList(iv.length).setAll(0, iv);
      61          27 :       dataMem.asTypedList(input.length).setAll(0, input);
      62          18 :       final ctx = EVP_CIPHER_CTX_new();
      63          27 :       EVP_EncryptInit_ex(ctx, alg, nullptr, keyMem, ivMem);
      64          27 :       EVP_EncryptUpdate(ctx, dataMem, lenMem, dataMem, input.length);
      65          27 :       EVP_EncryptFinal_ex(ctx, dataMem.elementAt(lenMem.value), lenMem);
      66          18 :       EVP_CIPHER_CTX_free(ctx);
      67          27 :       return Uint8List.fromList(dataMem.asTypedList(input.length));
      68             :     } finally {
      69           9 :       malloc.free(mem);
      70             :     }
      71             :   }
      72             : }
      73             : 
      74          27 : final Cipher aesCtr = _AesCtr();
      75             : 
      76             : class _AesCtr extends Cipher {
      77          18 :   _AesCtr() : super._();
      78             : 
      79           9 :   @override
      80             :   Pointer<NativeType> getAlg(int keysize) {
      81             :     switch (keysize) {
      82           9 :       case 128:
      83           0 :         return EVP_aes_128_ctr();
      84           9 :       case 256:
      85          18 :         return EVP_aes_256_ctr();
      86             :       default:
      87           0 :         throw ArgumentError('invalid key size');
      88             :     }
      89             :   }
      90             : }
      91             : 
      92           2 : FutureOr<Uint8List> pbkdf2(
      93             :     Uint8List passphrase, Uint8List salt, Hash hash, int iterations, int bits) {
      94           2 :   final outLen = bits ~/ 8;
      95           8 :   final mem = malloc.call<Uint8>(passphrase.length + salt.length + outLen);
      96           4 :   final saltMem = mem.elementAt(passphrase.length);
      97           4 :   final outMem = saltMem.elementAt(salt.length);
      98             :   try {
      99           6 :     mem.asTypedList(passphrase.length).setAll(0, passphrase);
     100           6 :     saltMem.asTypedList(salt.length).setAll(0, salt);
     101           8 :     PKCS5_PBKDF2_HMAC(mem, passphrase.length, saltMem, salt.length, iterations,
     102           2 :         hash.ptr, outLen, outMem);
     103           4 :     return Uint8List.fromList(outMem.asTypedList(outLen));
     104             :   } finally {
     105           2 :     malloc.free(mem);
     106             :   }
     107             : }

Generated by: LCOV version 1.14