diff --git a/lib/src/impl_ffi/impl_ffi.aes_common.dart b/lib/src/impl_ffi/impl_ffi.aes_common.dart index 0ce7e08a..70d014b4 100644 --- a/lib/src/impl_ffi/impl_ffi.aes_common.dart +++ b/lib/src/impl_ffi/impl_ffi.aes_common.dart @@ -15,7 +15,6 @@ part of impl_ffi; Uint8List _aesImportRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); if (keyData.length == 24) { // 192-bit AES is intentionally unsupported, see https://crbug.com/533699 // If not supported in Chrome, there is not reason to support it in Dart. @@ -31,8 +30,6 @@ Uint8List _aesImportJwkKey( Map jwk, { required String expectedJwkAlgSuffix, }) { - ArgumentError.checkNotNull(jwk, 'jwk'); - final k = JsonWebKey.fromJson(jwk); void checkJwk(bool condition, String prop, String message) => @@ -79,7 +76,6 @@ Map _aesExportJwkKey( } Uint8List _aesGenerateKey(int length) { - ArgumentError.checkNotNull(length, 'length'); if (length == 192) { // 192-bit AES is intentionally unsupported, see https://crbug.com/533699 // If not supported in Chrome, there is not reason to support it in Dart. diff --git a/lib/src/impl_ffi/impl_ffi.aescbc.dart b/lib/src/impl_ffi/impl_ffi.aescbc.dart index c1990ae4..a49be325 100644 --- a/lib/src/impl_ffi/impl_ffi.aescbc.dart +++ b/lib/src/impl_ffi/impl_ffi.aescbc.dart @@ -35,9 +35,8 @@ Stream _aesCbcEncryptOrDecrypt( bool encrypt, Stream> source, List iv, -) async* { - final scope = _Scope(); - try { +) { + return _Scope.stream((scope) async* { assert(key.length == 16 || key.length == 32); final cipher = key.length == 16 ? ssl.EVP_aes_128_cbc() : ssl.EVP_aes_256_cbc(); @@ -91,9 +90,7 @@ Stream _aesCbcEncryptOrDecrypt( if (outLen.value > 0) { yield outData.sublist(0, outLen.value); } - } finally { - scope.release(); - } + }); } class _AesCbcSecretKey implements AesCbcSecretKey { @@ -101,32 +98,20 @@ class _AesCbcSecretKey implements AesCbcSecretKey { _AesCbcSecretKey(this._key); @override - Future decryptBytes(List data, List iv) async { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); - return await _bufferStream(decryptStream(Stream.value(data), iv)); - } + Future decryptBytes(List data, List iv) async => + await _bufferStream(decryptStream(Stream.value(data), iv)); @override - Stream decryptStream(Stream> data, List iv) { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); - return _aesCbcEncryptOrDecrypt(_key, false, data, iv); - } + Stream decryptStream(Stream> data, List iv) => + _aesCbcEncryptOrDecrypt(_key, false, data, iv); @override - Future encryptBytes(List data, List iv) async { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); - return await _bufferStream(encryptStream(Stream.value(data), iv)); - } + Future encryptBytes(List data, List iv) async => + await _bufferStream(encryptStream(Stream.value(data), iv)); @override - Stream encryptStream(Stream> data, List iv) { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); - return _aesCbcEncryptOrDecrypt(_key, true, data, iv); - } + Stream encryptStream(Stream> data, List iv) => + _aesCbcEncryptOrDecrypt(_key, true, data, iv); @override Future> exportJsonWebKey() async => diff --git a/lib/src/impl_ffi/impl_ffi.aesctr.dart b/lib/src/impl_ffi/impl_ffi.aesctr.dart index efee8bc5..f569b968 100644 --- a/lib/src/impl_ffi/impl_ffi.aesctr.dart +++ b/lib/src/impl_ffi/impl_ffi.aesctr.dart @@ -58,12 +58,11 @@ Stream _aesCtrEncryptOrDecrypt( Stream> source, List counter, int length, -) async* { +) { // Heavily inspired by Chromium Web Crypto implementation, see: // https://chromium.googlesource.com/chromium/src/+/43d62c50b705f88c67b14539e91fd8fd017f70c4/components/webcrypto/algorithms/aes_ctr.cc#144 - final scope = _Scope(); - try { + return _Scope.stream((scope) async* { assert(counter.length == 16); assert(key.length == 16 || key.length == 32); final cipher = @@ -198,9 +197,7 @@ Stream _aesCtrEncryptOrDecrypt( if (outLen.value > 0) { yield outData.sublist(0, outLen.value); } - } finally { - scope.release(); - } + }); } class _AesCtrSecretKey implements AesCtrSecretKey { @@ -211,8 +208,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) { - ArgumentError.checkNotNull(counter, 'counter'); - ArgumentError.checkNotNull(length, 'length'); if (counter.length != 16) { throw ArgumentError.value(counter, 'counter', 'must be 16 bytes'); } @@ -227,7 +222,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) async { - ArgumentError.checkNotNull(data, 'data'); _checkArguments(counter, length); return await _bufferStream(decryptStream( Stream.value(data), @@ -242,7 +236,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) { - ArgumentError.checkNotNull(data, 'data'); _checkArguments(counter, length); return _aesCtrEncryptOrDecrypt(_key, false, data, counter, length); } @@ -253,7 +246,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) async { - ArgumentError.checkNotNull(data, 'data'); _checkArguments(counter, length); return await _bufferStream(encryptStream( Stream.value(data), @@ -268,7 +260,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) { - ArgumentError.checkNotNull(data, 'data'); _checkArguments(counter, length); return _aesCtrEncryptOrDecrypt(_key, true, data, counter, length); } diff --git a/lib/src/impl_ffi/impl_ffi.aesgcm.dart b/lib/src/impl_ffi/impl_ffi.aesgcm.dart index 9fc88cb8..c8871d04 100644 --- a/lib/src/impl_ffi/impl_ffi.aesgcm.dart +++ b/lib/src/impl_ffi/impl_ffi.aesgcm.dart @@ -58,8 +58,7 @@ Future _aesGcmEncryptDecrypt( // what chrome does, how firefox passes tests. And check if other // primitives that accept an iv/nonce has size limitations on it. - final scope = _Scope(); - try { + return _Scope.async((scope) async { assert(key.length == 16 || key.length == 32); final aead = key.length == 16 ? ssl.EVP_aead_aes_128_gcm() @@ -78,40 +77,38 @@ Future _aesGcmEncryptDecrypt( if (isEncrypt) { final outLen = scope(); final maxOut = data.length + ssl.EVP_AEAD_max_overhead(aead); - return _withOutPointer(maxOut, (ffi.Pointer out) { - _checkOpIsOne(ssl.EVP_AEAD_CTX_seal( - ctx, - out, - outLen, - maxOut, - scope.dataAsPointer(iv), - iv.length, - scope.dataAsPointer(data), - data.length, - scope.dataAsPointer(additionalData_), - additionalData_.length, - )); - }).sublist(0, outLen.value); + final out = scope(maxOut); + _checkOpIsOne(ssl.EVP_AEAD_CTX_seal( + ctx, + out, + outLen, + maxOut, + scope.dataAsPointer(iv), + iv.length, + scope.dataAsPointer(data), + data.length, + scope.dataAsPointer(additionalData_), + additionalData_.length, + )); + return out.copy(outLen.value); } else { final outLen = scope(); - return _withOutPointer(data.length, (ffi.Pointer out) { - _checkOpIsOne(ssl.EVP_AEAD_CTX_open( - ctx, - out, - outLen, - data.length, - scope.dataAsPointer(iv), - iv.length, - scope.dataAsPointer(data), - data.length, - scope.dataAsPointer(additionalData_), - additionalData_.length, - )); - }).sublist(0, outLen.value); + final out = scope(data.length); + _checkOpIsOne(ssl.EVP_AEAD_CTX_open( + ctx, + out, + outLen, + data.length, + scope.dataAsPointer(iv), + iv.length, + scope.dataAsPointer(data), + data.length, + scope.dataAsPointer(additionalData_), + additionalData_.length, + )); + return out.copy(outLen.value); } - } finally { - scope.release(); - } + }); } class _AesGcmSecretKey implements AesGcmSecretKey { diff --git a/lib/src/impl_ffi/impl_ffi.digest.dart b/lib/src/impl_ffi/impl_ffi.digest.dart index a6826ec5..ae522f70 100644 --- a/lib/src/impl_ffi/impl_ffi.digest.dart +++ b/lib/src/impl_ffi/impl_ffi.digest.dart @@ -18,8 +18,6 @@ abstract class _Hash implements Hash { const _Hash(); factory _Hash.fromHash(Hash hash) { - ArgumentError.checkNotNull(hash, 'hash'); - if (hash is _Hash) { return hash; } @@ -41,24 +39,27 @@ abstract class _Hash implements Hash { } @override - Future digestBytes(List data) { - ArgumentError.checkNotNull(data, 'data'); - - return digestStream(Stream.value(data)); - } + Future digestBytes(List data) => + digestStream(Stream.value(data)); @override - Future digestStream(Stream> data) async { - ArgumentError.checkNotNull(data, 'data'); - - return await _withEVP_MD_CTX((ctx) async { + Future digestStream(Stream> data) { + return _Scope.async((scope) async { + final ctx = scope.create(ssl.EVP_MD_CTX_new, ssl.EVP_MD_CTX_free); + // Initialize with hash function _checkOp(ssl.EVP_DigestInit(ctx, _md) == 1); + + // Stream data await _streamToUpdate(data, ctx, ssl.EVP_DigestUpdate); + + // Get size of the output buffer final size = ssl.EVP_MD_CTX_size(ctx); - _checkOp(size > 0); - return _withOutPointer(size, (ffi.Pointer p) { - _checkOp(ssl.EVP_DigestFinal(ctx, p, ffi.nullptr) == 1); - }); + _checkOp(size > 0); // sanity check + + // Allocate output buffer and return output + final out = scope(size); + _checkOp(ssl.EVP_DigestFinal(ctx, out, ffi.nullptr) == 1); + return out.copy(size); }); } } diff --git a/lib/src/impl_ffi/impl_ffi.ec_common.dart b/lib/src/impl_ffi/impl_ffi.ec_common.dart index af732546..7a25062b 100644 --- a/lib/src/impl_ffi/impl_ffi.ec_common.dart +++ b/lib/src/impl_ffi/impl_ffi.ec_common.dart @@ -16,8 +16,6 @@ part of impl_ffi; /// Get `ssl.NID_...` from BoringSSL matching the given [curve]. int _ecCurveToNID(EllipticCurve curve) { - ArgumentError.checkNotNull(curve, 'curve'); - if (curve == EllipticCurve.p256) { return NID_X9_62_prime256v1; } @@ -47,8 +45,6 @@ EllipticCurve _ecCurveFromNID(int nid) { } String _ecCurveToJwkCrv(EllipticCurve curve) { - ArgumentError.checkNotNull(curve, 'curve'); - if (curve == EllipticCurve.p256) { return 'P-256'; } @@ -67,8 +63,7 @@ void _validateEllipticCurveKey( _EvpPKey key, EllipticCurve curve, ) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { _checkData(ssl.EVP_PKEY_id.invoke(key) == EVP_PKEY_EC, message: 'key is not an EC key'); @@ -88,9 +83,7 @@ void _validateEllipticCurveKey( final nid = ssl.EC_GROUP_get_curve_name(ssl.EC_KEY_get0_group(ec)); _checkData(_ecCurveToNID(curve) == nid, message: 'incorrect elliptic curve'); - } finally { - scope.release(); - } + }); } _EvpPKey _importPkcs8EcPrivateKey( @@ -164,8 +157,7 @@ _EvpPKey _importJwkEcPrivateOrPublicKey( // TODO: Reject keys with key_ops in inconsistent with isPrivateKey // Also in the js implementation... - final scope = _Scope(); - try { + return _Scope.sync((scope) { final ec = ssl.EC_KEY_new_by_curve_name(_ecCurveToNID(curve)); _checkOp(ec.address != 0, fallback: 'internal failure to use curve'); scope.defer(() => ssl.EC_KEY_free(ec)); @@ -216,9 +208,7 @@ _EvpPKey _importJwkEcPrivateOrPublicKey( _checkOpIsOne(ssl.EVP_PKEY_set1_EC_KEY.invoke(key, ec)); return key; - } finally { - scope.release(); - } + }); } _EvpPKey _importRawEcPublicKey( @@ -226,44 +216,42 @@ _EvpPKey _importRawEcPublicKey( EllipticCurve curve, ) { // See: https://chromium.googlesource.com/chromium/src/+/43d62c50b705f88c67b14539e91fd8fd017f70c4/components/webcrypto/algorithms/ec.cc#332 + return _Scope.sync((scope) { + // Create EC_KEY for the curve + final ec = ssl.EC_KEY_new_by_curve_name(_ecCurveToNID(curve)); + _checkOp(ec.address != 0, fallback: 'internal failure to use curve'); + scope.defer(() => ssl.EC_KEY_free(ec)); - // Create EC_KEY for the curve - final ec = ssl.EC_KEY_new_by_curve_name(_ecCurveToNID(curve)); - _checkOp(ec.address != 0, fallback: 'internal failure to use curve'); - - try { // Create EC_POINT to hold public key info final pub = ssl.EC_POINT_new(ssl.EC_KEY_get0_group(ec)); _checkOp(pub.address != 0, fallback: 'internal point allocation error'); - try { - // Read raw public key - _withDataAsPointer(keyData, (ffi.Pointer p) { - _checkDataIsOne( - ssl.EC_POINT_oct2point( - ssl.EC_KEY_get0_group(ec), pub, p, keyData.length, ffi.nullptr), - fallback: 'invalid keyData', - ); - }); - // Copy pub point to ec - _checkDataIsOne(ssl.EC_KEY_set_public_key(ec, pub), - fallback: 'invalid keyData'); - - final key = _EvpPKey(); - _checkOpIsOne(ssl.EVP_PKEY_set1_EC_KEY.invoke(key, ec)); - _validateEllipticCurveKey(key, curve); - - return key; - } finally { - ssl.EC_POINT_free(pub); - } - } finally { - ssl.EC_KEY_free(ec); - } + scope.defer(() => ssl.EC_POINT_free(pub)); + + // Read raw public key + _checkDataIsOne( + ssl.EC_POINT_oct2point( + ssl.EC_KEY_get0_group(ec), + pub, + scope.dataAsPointer(keyData), + keyData.length, + ffi.nullptr, + ), + fallback: 'invalid keyData', + ); + // Copy pub point to ec + _checkDataIsOne(ssl.EC_KEY_set_public_key(ec, pub), + fallback: 'invalid keyData'); + + final key = _EvpPKey(); + _checkOpIsOne(ssl.EVP_PKEY_set1_EC_KEY.invoke(key, ec)); + _validateEllipticCurveKey(key, curve); + + return key; + }); } Uint8List _exportRawEcPublicKey(_EvpPKey key) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final ec = ssl.EVP_PKEY_get1_EC_KEY.invoke(key); _checkOp(ec.address != 0, fallback: 'internal key type invariant error'); scope.defer(() => ssl.EC_KEY_free(ec)); @@ -279,9 +267,7 @@ Uint8List _exportRawEcPublicKey(_EvpPKey key) { ), fallback: 'formatting failed'); }); - } finally { - scope.release(); - } + }); } Map _exportJwkEcPrivateOrPublicKey( @@ -289,8 +275,7 @@ Map _exportJwkEcPrivateOrPublicKey( required bool isPrivateKey, String? jwkUse, }) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final ec = ssl.EVP_PKEY_get1_EC_KEY.invoke(key); _checkOp(ec.address != 0, fallback: 'internal key type invariant error'); scope.defer(() => ssl.EC_KEY_free(ec)); @@ -312,39 +297,36 @@ Map _exportJwkEcPrivateOrPublicKey( ffi.nullptr, )); - final xAsBytes = _withOutPointer(paramSize, (ffi.Pointer p) { - _checkOpIsOne(ssl.BN_bn2bin_padded(p, paramSize, x)); - }); - final yAsBytes = _withOutPointer(paramSize, (ffi.Pointer p) { - _checkOpIsOne(ssl.BN_bn2bin_padded(p, paramSize, y)); - }); + // Create an output buffer + final out = scope(paramSize); - Uint8List? dAsBytes; + _checkOpIsOne(ssl.BN_bn2bin_padded(out, paramSize, x)); + final xBytes = out.copy(paramSize); + _checkOpIsOne(ssl.BN_bn2bin_padded(out, paramSize, y)); + final yBytes = out.copy(paramSize); + + Uint8List? dBytes; if (isPrivateKey) { final d = ssl.EC_KEY_get0_private_key(ec); - dAsBytes = _withOutPointer(paramSize, (ffi.Pointer p) { - _checkOpIsOne(ssl.BN_bn2bin_padded(p, paramSize, d)); - }); + _checkOpIsOne(ssl.BN_bn2bin_padded(out, paramSize, d)); + dBytes = out.copy(paramSize); } return JsonWebKey( kty: 'EC', use: jwkUse, crv: _ecCurveToJwkCrv(curve), - x: _jwkEncodeBase64UrlNoPadding(xAsBytes), - y: _jwkEncodeBase64UrlNoPadding(yAsBytes), - d: dAsBytes != null ? _jwkEncodeBase64UrlNoPadding(dAsBytes) : null, + x: _jwkEncodeBase64UrlNoPadding(xBytes), + y: _jwkEncodeBase64UrlNoPadding(yBytes), + d: dBytes != null ? _jwkEncodeBase64UrlNoPadding(dBytes) : null, ).toJson(); - } finally { - scope.release(); - } + }); } KeyPair<_EvpPKey, _EvpPKey> _generateEcKeyPair( EllipticCurve curve, ) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final ecPriv = ssl.EC_KEY_new_by_curve_name(_ecCurveToNID(curve)); _checkOp(ecPriv.address != 0, fallback: 'internal failure to use curve'); scope.defer(() => ssl.EC_KEY_free(ecPriv)); @@ -369,7 +351,5 @@ KeyPair<_EvpPKey, _EvpPKey> _generateEcKeyPair( privateKey: privKey, publicKey: pubKey, ); - } finally { - scope.release(); - } + }); } diff --git a/lib/src/impl_ffi/impl_ffi.ecdh.dart b/lib/src/impl_ffi/impl_ffi.ecdh.dart index 58986f7e..b96c474c 100644 --- a/lib/src/impl_ffi/impl_ffi.ecdh.dart +++ b/lib/src/impl_ffi/impl_ffi.ecdh.dart @@ -75,8 +75,6 @@ class _EcdhPrivateKey implements EcdhPrivateKey { @override Future deriveBits(int length, EcdhPublicKey publicKey) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(publicKey, 'publicKey'); if (publicKey is! _EcdhPublicKey) { throw ArgumentError.value( publicKey, @@ -88,8 +86,7 @@ class _EcdhPrivateKey implements EcdhPrivateKey { throw ArgumentError.value(length, 'length', 'must be positive'); } - final scope = _Scope(); - try { + return _Scope.async((scope) async { final pubEcKey = ssl.EVP_PKEY_get1_EC_KEY.invoke(publicKey._key); _checkOp(pubEcKey.address != 0, fallback: 'not an ec key'); scope.defer(() => ssl.EC_KEY_free(pubEcKey)); @@ -123,7 +120,7 @@ class _EcdhPrivateKey implements EcdhPrivateKey { } if (length == 0) { - return Uint8List.fromList([]); + return Uint8List.fromList(const []); } final lengthInBytes = (length / 8).ceil(); @@ -150,9 +147,7 @@ class _EcdhPrivateKey implements EcdhPrivateKey { } return derived; - } finally { - scope.release(); - } + }); } @override diff --git a/lib/src/impl_ffi/impl_ffi.ecdsa.dart b/lib/src/impl_ffi/impl_ffi.ecdsa.dart index a8991aef..174993a0 100644 --- a/lib/src/impl_ffi/impl_ffi.ecdsa.dart +++ b/lib/src/impl_ffi/impl_ffi.ecdsa.dart @@ -18,8 +18,6 @@ part of impl_ffi; /// Get valid value for `jwk.alg` property given an [EllipticCurve] for ECDSA. String _ecdsaCurveToJwkAlg(EllipticCurve curve) { - ArgumentError.checkNotNull(curve, 'curve'); - if (curve == EllipticCurve.p256) { return 'ES256'; } @@ -94,8 +92,8 @@ Uint8List _convertEcdsaDerSignatureToWebCryptoSignature( _EvpPKey key, Uint8List signature, ) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { + // TODO: Check if cbs is empty after parsing, consider using ECDSA_SIG_from_bytes instead (like chrome does) final ecdsa = _withDataAsCBS(signature, ssl.ECDSA_SIG_parse); _checkOp(ecdsa.address != 0, message: 'internal error formatting signature'); @@ -129,9 +127,7 @@ Uint8List _convertEcdsaDerSignatureToWebCryptoSignature( ); }); }); - } finally { - scope.release(); - } + }); } /// Convert ECDSA signature in the raw R + S as specified in webcrypto to DER @@ -144,8 +140,7 @@ Uint8List? _convertEcdsaWebCryptoSignatureToDerSignature( _EvpPKey key, List signature, ) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { // Read EC key and get the number of bytes required to encode R and S. final ec = ssl.EVP_PKEY_get1_EC_KEY.invoke(key); _checkOp(ec.address != 0, message: 'internal key type invariant violation'); @@ -189,9 +184,7 @@ Uint8List? _convertEcdsaWebCryptoSignatureToDerSignature( fallback: 'internal error reformatting signature', )); }); - } finally { - scope.release(); - } + }); } class _EcdsaPrivateKey implements EcdsaPrivateKey { @@ -200,16 +193,11 @@ class _EcdsaPrivateKey implements EcdsaPrivateKey { _EcdsaPrivateKey(this._key); @override - Future signBytes(List data, Hash hash) { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(hash, 'hash'); - return signStream(Stream.value(data), hash); - } + Future signBytes(List data, Hash hash) => + signStream(Stream.value(data), hash); @override Future signStream(Stream> data, Hash hash) async { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(hash, 'hash'); final md = _Hash.fromHash(hash)._md; final sig = await _withEVP_MD_CTX((ctx) async { @@ -252,12 +240,8 @@ class _EcdsaPublicKey implements EcdsaPublicKey { _EcdsaPublicKey(this._key); @override - Future verifyBytes(List signature, List data, Hash hash) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(hash, 'hash'); - return verifyStream(signature, Stream.value(data), hash); - } + Future verifyBytes(List signature, List data, Hash hash) => + verifyStream(signature, Stream.value(data), hash); @override Future verifyStream( @@ -265,9 +249,6 @@ class _EcdsaPublicKey implements EcdsaPublicKey { Stream> data, Hash hash, ) async { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(hash, 'hash'); final md = _Hash.fromHash(hash)._md; // Convert to DER signature diff --git a/lib/src/impl_ffi/impl_ffi.hkdf.dart b/lib/src/impl_ffi/impl_ffi.hkdf.dart index da9ba218..6bd9d4b0 100644 --- a/lib/src/impl_ffi/impl_ffi.hkdf.dart +++ b/lib/src/impl_ffi/impl_ffi.hkdf.dart @@ -16,10 +16,8 @@ part of impl_ffi; -Future hkdfSecretKey_importRawKey(List keyData) async { - ArgumentError.checkNotNull(keyData, 'keyData'); - return _HkdfSecretKey(Uint8List.fromList(keyData)); -} +Future hkdfSecretKey_importRawKey(List keyData) async => + _HkdfSecretKey(Uint8List.fromList(keyData)); class _HkdfSecretKey implements HkdfSecretKey { final Uint8List _key; @@ -33,10 +31,6 @@ class _HkdfSecretKey implements HkdfSecretKey { List salt, List info, ) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(hash, 'hash'); - ArgumentError.checkNotNull(salt, 'salt'); - ArgumentError.checkNotNull(info, 'info'); if (length < 0) { throw ArgumentError.value(length, 'length', 'must be positive integer'); } @@ -50,8 +44,7 @@ class _HkdfSecretKey implements HkdfSecretKey { final lengthInBytes = length ~/ 8; - final scope = _Scope(); - try { + return _Scope.async((scope) async { return _withOutPointer(lengthInBytes, (ffi.Pointer out) { final r = ssl.HKDF( out, @@ -76,8 +69,6 @@ class _HkdfSecretKey implements HkdfSecretKey { _checkOpIsOne(r, fallback: 'HKDF key derivation failed'); } }); - } finally { - scope.release(); - } + }); } } diff --git a/lib/src/impl_ffi/impl_ffi.hmac.dart b/lib/src/impl_ffi/impl_ffi.hmac.dart index 8ea33219..247edefd 100644 --- a/lib/src/impl_ffi/impl_ffi.hmac.dart +++ b/lib/src/impl_ffi/impl_ffi.hmac.dart @@ -65,9 +65,6 @@ Future hmacSecretKey_importJsonWebKey( Hash hash, { int? length, }) async { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - final h = _Hash.fromHash(hash); final k = JsonWebKey.fromJson(jwk); @@ -109,11 +106,7 @@ class _HmacSecretKey implements HmacSecretKey { _HmacSecretKey(this._keyData, this._hash); @override - Future signBytes(List data) { - ArgumentError.checkNotNull(data, 'data'); - - return signStream(Stream.value(data)); - } + Future signBytes(List data) => signStream(Stream.value(data)); @override Future signStream(Stream> data) async { @@ -141,18 +134,11 @@ class _HmacSecretKey implements HmacSecretKey { } @override - Future verifyBytes(List signature, List data) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - - return verifyStream(signature, Stream.value(data)); - } + Future verifyBytes(List signature, List data) => + verifyStream(signature, Stream.value(data)); @override Future verifyStream(List signature, Stream> data) async { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - final other = await signStream(data); if (signature.length != other.length) { return false; diff --git a/lib/src/impl_ffi/impl_ffi.pbkdf2.dart b/lib/src/impl_ffi/impl_ffi.pbkdf2.dart index bed6624c..dbe2762b 100644 --- a/lib/src/impl_ffi/impl_ffi.pbkdf2.dart +++ b/lib/src/impl_ffi/impl_ffi.pbkdf2.dart @@ -17,7 +17,6 @@ part of impl_ffi; Future pbkdf2SecretKey_importRawKey(List keyData) async { - ArgumentError.checkNotNull(keyData, 'keyData'); return _Pbkdf2SecretKey(Uint8List.fromList(keyData)); } @@ -33,10 +32,6 @@ class _Pbkdf2SecretKey implements Pbkdf2SecretKey { List salt, int iterations, ) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(hash, 'hash'); - ArgumentError.checkNotNull(salt, 'salt'); - ArgumentError.checkNotNull(iterations, 'iterations'); if (length < 0) { throw ArgumentError.value(length, 'length', 'must be positive integer'); } @@ -59,8 +54,7 @@ class _Pbkdf2SecretKey implements Pbkdf2SecretKey { final lengthInBytes = length ~/ 8; - final scope = _Scope(); - try { + return _Scope.async((scope) async { return _withOutPointer(lengthInBytes, (ffi.Pointer out) { _checkOpIsOne(ssl.PKCS5_PBKDF2_HMAC( scope.dataAsPointer(_key), @@ -73,8 +67,6 @@ class _Pbkdf2SecretKey implements Pbkdf2SecretKey { out, )); }); - } finally { - scope.release(); - } + }); } } diff --git a/lib/src/impl_ffi/impl_ffi.rsa_common.dart b/lib/src/impl_ffi/impl_ffi.rsa_common.dart index b02afe2b..e9bcf7e7 100644 --- a/lib/src/impl_ffi/impl_ffi.rsa_common.dart +++ b/lib/src/impl_ffi/impl_ffi.rsa_common.dart @@ -15,8 +15,7 @@ part of impl_ffi; _EvpPKey _importPkcs8RsaPrivateKey(List keyData) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final k = _withDataAsCBS(keyData, ssl.EVP_parse_private_key); _checkData(k.address != 0, fallback: 'unable to parse key'); final key = _EvpPKey.wrap(k); @@ -31,14 +30,11 @@ _EvpPKey _importPkcs8RsaPrivateKey(List keyData) { _checkData(ssl.RSA_check_key(rsa) == 1, fallback: 'invalid key'); return key; - } finally { - scope.release(); - } + }); } _EvpPKey _importSpkiRsaPublicKey(List keyData) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final k = _withDataAsCBS(keyData, ssl.EVP_parse_public_key); _checkData(k.address != 0, fallback: 'unable to parse key'); final key = _EvpPKey.wrap(k); @@ -53,9 +49,7 @@ _EvpPKey _importSpkiRsaPublicKey(List keyData) { _checkData(ssl.RSA_check_key(rsa) == 1, fallback: 'invalid key'); return key; - } finally { - scope.release(); - } + }); } _EvpPKey _importJwkRsaPrivateOrPublicKey( @@ -64,8 +58,7 @@ _EvpPKey _importJwkRsaPrivateOrPublicKey( required String expectedAlg, required String expectedUse, }) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { void checkJwk( bool condition, String prop, [ @@ -167,9 +160,7 @@ _EvpPKey _importJwkRsaPrivateOrPublicKey( _checkOpIsOne(ssl.EVP_PKEY_set1_RSA.invoke(key, rsa)); return key; - } finally { - scope.release(); - } + }); } Map _exportJwkRsaPrivateOrPublicKey( @@ -178,8 +169,7 @@ Map _exportJwkRsaPrivateOrPublicKey( required String jwkAlg, required String jwkUse, }) { - final scope = _Scope(); - try { + return _Scope.sync((scope) { final rsa = ssl.EVP_PKEY_get1_RSA.invoke(key); _checkOp(rsa.address != 0, fallback: 'internal key type error'); scope.defer(() => ssl.RSA_free(rsa)); @@ -236,9 +226,7 @@ Map _exportJwkRsaPrivateOrPublicKey( dq: encodeBN(dq.value), qi: encodeBN(qi.value), ).toJson(); - } finally { - scope.release(); - } + }); } _KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair( @@ -263,8 +251,7 @@ _KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair( throw UnsupportedError('publicExponent is not supported, try 3 or 65537'); } - final scope = _Scope(); - try { + return _Scope.sync((scope) { // Generate private RSA key final privRSA = scope.create(ssl.RSA_new, ssl.RSA_free); @@ -295,7 +282,5 @@ _KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair( privateKey: privKey, publicKey: pubKey, ); - } finally { - scope.release(); - } + }); } diff --git a/lib/src/impl_ffi/impl_ffi.rsapss.dart b/lib/src/impl_ffi/impl_ffi.rsapss.dart index a4aaa7f3..2d1c5191 100644 --- a/lib/src/impl_ffi/impl_ffi.rsapss.dart +++ b/lib/src/impl_ffi/impl_ffi.rsapss.dart @@ -107,15 +107,11 @@ class _RsaPssPrivateKey implements RsaPssPrivateKey { @override Future signBytes(List data, int saltLength) { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(saltLength, 'saltLength'); return signStream(Stream.value(data), saltLength); } @override Future signStream(Stream> data, int saltLength) { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(saltLength, 'saltLength'); if (saltLength < 0) { throw ArgumentError.value( saltLength, @@ -181,12 +177,8 @@ class _RsaPssPublicKey implements RsaPssPublicKey { List signature, List data, int saltLength, - ) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(saltLength, 'saltLength'); - return verifyStream(signature, Stream.value(data), saltLength); - } + ) => + verifyStream(signature, Stream.value(data), saltLength); @override Future verifyStream( @@ -194,9 +186,6 @@ class _RsaPssPublicKey implements RsaPssPublicKey { Stream> data, int saltLength, ) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(saltLength, 'saltLength'); if (saltLength < 0) { throw ArgumentError.value( saltLength, diff --git a/lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart b/lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart index ed1439ff..5f49ce42 100644 --- a/lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart +++ b/lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart @@ -107,15 +107,10 @@ class _RsassaPkcs1V15PrivateKey implements RsassaPkcs1V15PrivateKey { _RsassaPkcs1V15PrivateKey(this._key, this._hash); @override - Future signBytes(List data) { - ArgumentError.checkNotNull(data, 'data'); - return signStream(Stream.value(data)); - } + Future signBytes(List data) => signStream(Stream.value(data)); @override Future signStream(Stream> data) { - ArgumentError.checkNotNull(data, 'data'); - return _withEVP_MD_CTX((ctx) async { return await _withPEVP_PKEY_CTX((pctx) async { _checkOpIsOne( @@ -162,17 +157,11 @@ class _RsassaPkcs1V15PublicKey implements RsassaPkcs1V15PublicKey { _RsassaPkcs1V15PublicKey(this._key, this._hash); @override - Future verifyBytes(List signature, List data) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - return verifyStream(signature, Stream.value(data)); - } + Future verifyBytes(List signature, List data) => + verifyStream(signature, Stream.value(data)); @override Future verifyStream(List signature, Stream> data) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - return _withEVP_MD_CTX((ctx) async { return _withPEVP_PKEY_CTX((pctx) async { _checkOpIsOne(ssl.EVP_DigestVerifyInit.invoke( diff --git a/lib/src/impl_ffi/impl_ffi.utils.dart b/lib/src/impl_ffi/impl_ffi.utils.dart index 8dabb6c2..896bdd97 100644 --- a/lib/src/impl_ffi/impl_ffi.utils.dart +++ b/lib/src/impl_ffi/impl_ffi.utils.dart @@ -163,16 +163,10 @@ class _SslAllocator implements Allocator { /// /// Must be de-allocated with [free]. @override - ffi.Pointer allocate(int byteCount, - {int? alignment}) { - // TODO: Find out why OPENSSL_malloc doesn't work on Dart on Linux. - // This presumably has to do with dlopen(), WEAK symbols and the fact - // that the `dart` executable that ships in the Dart-SDK for Linux is - // a _release build_, not a _product build_, so more symbols might be - // visible. In anycase using ffi.allocate / ffi.free works fine on - // the `dart` executable with the Dart-SDK for Linux. - // Please note, that this does not work with the Flutter or the `dart` - // binary that ships with the Flutter SDK. + ffi.Pointer allocate( + int byteCount, { + int? alignment, + }) { final p = ssl.OPENSSL_malloc(byteCount); _checkOp(p.address != 0, fallback: 'allocation failure'); return p.cast(); @@ -204,8 +198,10 @@ class _Scope implements Allocator { /// Allocate an [ffi.Pointer] in this scope. @override - ffi.Pointer allocate(int byteCount, - {int? alignment}) { + ffi.Pointer allocate( + int byteCount, { + int? alignment, + }) { final p = _sslAlloc.allocate(byteCount); defer(() => _sslAlloc.free(p), p); return p; @@ -244,7 +240,12 @@ class _Scope implements Allocator { } /// Release all resources held in this scope. - void release() { + /// + /// Instead of calling this directly, prefer to use: + /// * [_Scope.async], + /// * [_Scope.sync], or, + /// * [_Scope.stream]. + void _release() { while (_deferred.isNotEmpty) { try { _deferred.removeLast().fn(); @@ -266,6 +267,42 @@ class _Scope implements Allocator { // Does nothing, use `release` instead. // Not throwing, so that this can actually be used as an Allocator. } + + /// Run [fn] with a [_Scope] that is released when the [Future] returned + /// from [fn] is completed. + static Future async(FutureOr Function(_Scope scope) fn) async { + assert(T is! Future, 'avoid nested async blocks'); + final scope = _Scope(); + try { + return await fn(scope); + } finally { + scope._release(); + } + } + + /// Run [fn] with a [_Scope] that is released when the [Stream] returned + /// from [fn] is completed. + static Stream stream(Stream Function(_Scope scope) fn) async* { + final scope = _Scope(); + try { + yield* fn(scope); + } finally { + scope._release(); + } + } + + /// Run [fn] with a [_Scope] that is released when [fn] returns. + /// + /// Use [async] if [fn] is an async function that returns a [Future]. + static T sync(T Function(_Scope scope) fn) { + assert(T is! Future, 'avoid nested async blocks'); + final scope = _Scope(); + try { + return fn(scope); + } finally { + scope._release(); + } + } } /// Invoke [fn] with [p], and release [p] when [fn] returns. @@ -295,6 +332,11 @@ Future _withAllocationAsync( } } +extension on ffi.Pointer { + /// Copy [length] bytes from pointer to [Uint8List] owned by Dart. + Uint8List copy(int length) => Uint8List.fromList(asTypedList(length)); +} + /// Allocated a [size] bytes [ffi.Pointer] and call [fn], and copy the data /// from the pointer to an [Uint8List] when [fn] returns. Freeing the pointer /// when [fn] returns. @@ -408,13 +450,11 @@ Uint8List _withOutCBB(void Function(ffi.Pointer) fn) { /// Convert [Stream>] to [Uint8List]. Future _bufferStream(Stream> data) async { - ArgumentError.checkNotNull(data, 'data'); - final result = []; - // TODO: Make this allocation stuff smarter - await for (var chunk in data) { - result.addAll(chunk); + final b = BytesBuilder(); + await for (final chunk in data) { + b.add(chunk); } - return Uint8List.fromList(result); + return b.takeBytes(); } /// Get the number of bytes required to hold [numberOfBits]. diff --git a/lib/src/impl_js/impl_js.aescbc.dart b/lib/src/impl_js/impl_js.aescbc.dart index cff70f08..47086198 100644 --- a/lib/src/impl_js/impl_js.aescbc.dart +++ b/lib/src/impl_js/impl_js.aescbc.dart @@ -53,8 +53,6 @@ class _AesCbcSecretKey implements AesCbcSecretKey { @override Future decryptBytes(List data, List iv) async { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); return await _decrypt( _aesCbcAlgorithm.update(iv: Uint8List.fromList(iv)), _key, @@ -69,8 +67,6 @@ class _AesCbcSecretKey implements AesCbcSecretKey { @override Future encryptBytes(List data, List iv) async { - ArgumentError.checkNotNull(data, 'data'); - ArgumentError.checkNotNull(iv, 'iv'); return await _encrypt( _aesCbcAlgorithm.update(iv: Uint8List.fromList(iv)), _key, diff --git a/lib/src/impl_js/impl_js.aesctr.dart b/lib/src/impl_js/impl_js.aesctr.dart index 2f420c94..bf288593 100644 --- a/lib/src/impl_js/impl_js.aesctr.dart +++ b/lib/src/impl_js/impl_js.aesctr.dart @@ -57,8 +57,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) async { - ArgumentError.checkNotNull(counter, 'counter'); - ArgumentError.checkNotNull(length, 'length'); return await _decrypt( _aesCtrAlgorithm.update( counter: Uint8List.fromList(counter), @@ -84,8 +82,6 @@ class _AesCtrSecretKey implements AesCtrSecretKey { List counter, int length, ) async { - ArgumentError.checkNotNull(counter, 'counter'); - ArgumentError.checkNotNull(length, 'length'); return await _encrypt( _aesCtrAlgorithm.update( counter: Uint8List.fromList(counter), diff --git a/lib/src/impl_js/impl_js.digest.dart b/lib/src/impl_js/impl_js.digest.dart index 79fc3ec3..da5db10a 100644 --- a/lib/src/impl_js/impl_js.digest.dart +++ b/lib/src/impl_js/impl_js.digest.dart @@ -20,8 +20,6 @@ class _Hash implements Hash { @override Future digestBytes(List data) async { - ArgumentError.checkNotNull(data, 'data'); - return await _handleDomException(() async { final result = await subtle.digest( _algorithm, @@ -44,8 +42,6 @@ const Hash sha512 = _Hash('SHA-512'); /// Get the algorithm from [hash] or throw an [ArgumentError]. String _getHashAlgorithm(Hash hash) { - ArgumentError.checkNotNull(hash, 'hash'); - if (hash is _Hash) { return hash._algorithm; } diff --git a/lib/src/impl_js/impl_js.ecdh.dart b/lib/src/impl_js/impl_js.ecdh.dart index 6a47cff2..7160a132 100644 --- a/lib/src/impl_js/impl_js.ecdh.dart +++ b/lib/src/impl_js/impl_js.ecdh.dart @@ -130,8 +130,6 @@ class _EcdhPrivateKey implements EcdhPrivateKey { @override Future deriveBits(int length, EcdhPublicKey publicKey) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(publicKey, 'publicKey'); if (publicKey is! _EcdhPublicKey) { throw ArgumentError.value( publicKey, diff --git a/lib/src/impl_js/impl_js.hkdf.dart b/lib/src/impl_js/impl_js.hkdf.dart index 6dedd0f9..a8c1f68f 100644 --- a/lib/src/impl_js/impl_js.hkdf.dart +++ b/lib/src/impl_js/impl_js.hkdf.dart @@ -42,9 +42,6 @@ class _HkdfSecretKey implements HkdfSecretKey { List salt, List info, ) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(salt, 'salt'); - ArgumentError.checkNotNull(info, 'info'); return await _deriveBits( subtle.Algorithm( name: _hkdfAlgorithmName, diff --git a/lib/src/impl_js/impl_js.pbkdf2.dart b/lib/src/impl_js/impl_js.pbkdf2.dart index e57fd99d..effa10c5 100644 --- a/lib/src/impl_js/impl_js.pbkdf2.dart +++ b/lib/src/impl_js/impl_js.pbkdf2.dart @@ -42,9 +42,6 @@ class _Pbkdf2SecretKey implements Pbkdf2SecretKey { List salt, int iterations, ) async { - ArgumentError.checkNotNull(length, 'length'); - ArgumentError.checkNotNull(salt, 'salt'); - ArgumentError.checkNotNull(iterations, 'iterations'); return await _deriveBits( subtle.Algorithm( name: _pbkdf2AlgorithmName, diff --git a/lib/src/impl_js/impl_js.rsapss.dart b/lib/src/impl_js/impl_js.rsapss.dart index d981b66e..87244094 100644 --- a/lib/src/impl_js/impl_js.rsapss.dart +++ b/lib/src/impl_js/impl_js.rsapss.dart @@ -94,7 +94,6 @@ class _RsaPssPrivateKey implements RsaPssPrivateKey { @override Future signBytes(List data, int saltLength) async { - ArgumentError.checkNotNull(saltLength, 'saltLength'); if (saltLength < 0) { throw ArgumentError.value( saltLength, @@ -136,7 +135,6 @@ class _RsaPssPublicKey implements RsaPssPublicKey { List data, int saltLength, ) async { - ArgumentError.checkNotNull(saltLength, 'saltLength'); if (saltLength < 0) { throw ArgumentError.value( saltLength, diff --git a/lib/src/impl_js/impl_js.utils.dart b/lib/src/impl_js/impl_js.utils.dart index 46ed5c93..83e57208 100644 --- a/lib/src/impl_js/impl_js.utils.dart +++ b/lib/src/impl_js/impl_js.utils.dart @@ -16,13 +16,11 @@ part of impl_js; /// Convert [Stream>] to [Uint8List]. Future _bufferStream(Stream> data) async { - ArgumentError.checkNotNull(data, 'data'); - final result = []; - // TODO: Make this allocation stuff smarter + final b = BytesBuilder(); await for (var chunk in data) { - result.addAll(chunk); + b.add(chunk); } - return Uint8List.fromList(result); + return b.takeBytes(); } /// Convert [publicExponent] to [Uint8List]. @@ -186,8 +184,6 @@ Future _sign( subtle.CryptoKey key, List data, ) { - ArgumentError.checkNotNull(data, 'data'); - return _handleDomException(() async { final result = await subtle.sign( algorithm, @@ -205,9 +201,6 @@ Future _verify( List signature, List data, ) { - ArgumentError.checkNotNull(signature, 'signature'); - ArgumentError.checkNotNull(data, 'data'); - return _handleDomException(() async { return await subtle.verify( algorithm, @@ -224,8 +217,6 @@ Future _encrypt( subtle.CryptoKey key, List data, ) { - ArgumentError.checkNotNull(data, 'data'); - return _handleDomException(() async { final result = await subtle.encrypt( algorithm, @@ -242,8 +233,6 @@ Future _decrypt( subtle.CryptoKey key, List data, ) { - ArgumentError.checkNotNull(data, 'data'); - return _handleDomException(() async { final result = await subtle.decrypt( algorithm, @@ -261,8 +250,6 @@ Future _deriveBits( int length, { bool invalidAccessErrorIsArgumentError = false, }) { - ArgumentError.checkNotNull(length, 'length'); - return _handleDomException(() async { final result = await subtle.deriveBits( algorithm, @@ -278,8 +265,6 @@ Future _exportKey( String format, subtle.CryptoKey key, ) { - ArgumentError.checkNotNull(format, 'format'); - return _handleDomException(() async { final result = await subtle.exportKey(format, key); return result.asUint8List(); diff --git a/lib/src/testing/utils/ffibonacci_chunked_stream.dart b/lib/src/testing/utils/ffibonacci_chunked_stream.dart index 44be1af0..67c38e79 100644 --- a/lib/src/testing/utils/ffibonacci_chunked_stream.dart +++ b/lib/src/testing/utils/ffibonacci_chunked_stream.dart @@ -14,7 +14,6 @@ /// Return the N'th fibonacci number. int _fibonacci(int n) { - ArgumentError.checkNotNull(n, 'n'); if (n < 0) { throw ArgumentError.value(n, 'n', 'must be a non-negative integer'); } diff --git a/lib/src/testing/utils/utils.dart b/lib/src/testing/utils/utils.dart index 181920f5..34c7a372 100644 --- a/lib/src/testing/utils/utils.dart +++ b/lib/src/testing/utils/utils.dart @@ -52,13 +52,11 @@ bool equalBytes(List a, List b) => base64Encode(a) == base64Encode(b); /// Convert [Stream>] to [Uint8List]. Future bufferStream(Stream> data) async { - ArgumentError.checkNotNull(data, 'data'); - final result = []; - // TODO: Make this allocation stuff smarter + final b = BytesBuilder(); await for (var chunk in data) { - result.addAll(chunk); + b.add(chunk); } - return Uint8List.fromList(result); + return b.takeBytes(); } Hash hashFromJson(dynamic json) { diff --git a/lib/src/webcrypto/webcrypto.aescbc.dart b/lib/src/webcrypto/webcrypto.aescbc.dart index fb68e19b..886b912c 100644 --- a/lib/src/webcrypto/webcrypto.aescbc.dart +++ b/lib/src/webcrypto/webcrypto.aescbc.dart @@ -61,20 +61,14 @@ abstract class AesCbcSecretKey { /// /// [1]: https://crbug.com/533699 static Future importRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); - return impl.aesCbc_importRawKey(keyData); } static Future importJsonWebKey(Map jwk) { - ArgumentError.checkNotNull(jwk, 'jwk'); - return impl.aesCbc_importJsonWebKey(jwk); } static Future generateKey(int length) { - ArgumentError.checkNotNull(length, 'length'); - return impl.aesCbc_generateKey(length); } diff --git a/lib/src/webcrypto/webcrypto.aesctr.dart b/lib/src/webcrypto/webcrypto.aesctr.dart index 01734b33..734f44ed 100644 --- a/lib/src/webcrypto/webcrypto.aesctr.dart +++ b/lib/src/webcrypto/webcrypto.aesctr.dart @@ -19,20 +19,14 @@ abstract class AesCtrSecretKey { AesCtrSecretKey._(); // keep the constructor private. static Future importRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); - return impl.aesCtr_importRawKey(keyData); } static Future importJsonWebKey(Map jwk) { - ArgumentError.checkNotNull(jwk, 'jwk'); - return impl.aesCtr_importJsonWebKey(jwk); } static Future generateKey(int length) { - ArgumentError.checkNotNull(length, 'length'); - return impl.aesCtr_generateKey(length); } diff --git a/lib/src/webcrypto/webcrypto.aesgcm.dart b/lib/src/webcrypto/webcrypto.aesgcm.dart index d8784477..241e3682 100644 --- a/lib/src/webcrypto/webcrypto.aesgcm.dart +++ b/lib/src/webcrypto/webcrypto.aesgcm.dart @@ -19,20 +19,14 @@ abstract class AesGcmSecretKey { AesGcmSecretKey._(); // keep the constructor private. static Future importRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); - return impl.aesGcm_importRawKey(keyData); } static Future importJsonWebKey(Map jwk) { - ArgumentError.checkNotNull(jwk, 'jwk'); - return impl.aesGcm_importJsonWebKey(jwk); } static Future generateKey(int length) { - ArgumentError.checkNotNull(length, 'length'); - return impl.aesGcm_generateKey(length); } diff --git a/lib/src/webcrypto/webcrypto.ecdh.dart b/lib/src/webcrypto/webcrypto.ecdh.dart index fa5169ac..882bd301 100644 --- a/lib/src/webcrypto/webcrypto.ecdh.dart +++ b/lib/src/webcrypto/webcrypto.ecdh.dart @@ -23,9 +23,6 @@ abstract class EcdhPrivateKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPrivateKey_importPkcs8Key(keyData, curve); } @@ -33,17 +30,12 @@ abstract class EcdhPrivateKey { Map jwk, EllipticCurve curve, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPrivateKey_importJsonWebKey(jwk, curve); } static Future> generateKey( EllipticCurve curve, ) { - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPrivateKey_generateKey(curve); } @@ -71,9 +63,6 @@ abstract class EcdhPublicKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPublicKey_importRawKey(keyData, curve); } @@ -95,9 +84,6 @@ abstract class EcdhPublicKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPublicKey_importSpkiKey(keyData, curve); } @@ -105,9 +91,6 @@ abstract class EcdhPublicKey { Map jwk, EllipticCurve curve, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdhPublicKey_importJsonWebKey(jwk, curve); } diff --git a/lib/src/webcrypto/webcrypto.ecdsa.dart b/lib/src/webcrypto/webcrypto.ecdsa.dart index 4c3b0a16..4d462b50 100644 --- a/lib/src/webcrypto/webcrypto.ecdsa.dart +++ b/lib/src/webcrypto/webcrypto.ecdsa.dart @@ -25,9 +25,6 @@ abstract class EcdsaPrivateKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPrivateKey_importPkcs8Key(keyData, curve); } @@ -35,17 +32,12 @@ abstract class EcdsaPrivateKey { Map jwk, EllipticCurve curve, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPrivateKey_importJsonWebKey(jwk, curve); } static Future> generateKey( EllipticCurve curve, ) { - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPrivateKey_generateKey(curve); } @@ -71,9 +63,6 @@ abstract class EcdsaPublicKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPublicKey_importRawKey(keyData, curve); } @@ -81,9 +70,6 @@ abstract class EcdsaPublicKey { List keyData, EllipticCurve curve, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPublicKey_importSpkiKey(keyData, curve); } @@ -91,9 +77,6 @@ abstract class EcdsaPublicKey { Map jwk, EllipticCurve curve, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(curve, 'curve'); - return impl.ecdsaPublicKey_importJsonWebKey(jwk, curve); } diff --git a/lib/src/webcrypto/webcrypto.hkdf.dart b/lib/src/webcrypto/webcrypto.hkdf.dart index 9fe4a02c..07c1f210 100644 --- a/lib/src/webcrypto/webcrypto.hkdf.dart +++ b/lib/src/webcrypto/webcrypto.hkdf.dart @@ -19,8 +19,6 @@ abstract class HkdfSecretKey { HkdfSecretKey._(); // keep the constructor private. static Future importRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); - return impl.hkdfSecretKey_importRawKey(keyData); } diff --git a/lib/src/webcrypto/webcrypto.hmac.dart b/lib/src/webcrypto/webcrypto.hmac.dart index 9d4f6902..61392f21 100644 --- a/lib/src/webcrypto/webcrypto.hmac.dart +++ b/lib/src/webcrypto/webcrypto.hmac.dart @@ -53,8 +53,6 @@ abstract class HmacSecretKey { Hash hash, { int? length, }) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); // These limitations are given in Web Cryptography Spec: // https://www.w3.org/TR/WebCryptoAPI/#hmac-operations if (length != null && length > keyData.length * 8) { @@ -89,8 +87,6 @@ abstract class HmacSecretKey { Hash hash, { int? length, }) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); /* TODO: Validate these in the native implememtation // These limitations are given in Web Cryptography Spec: @@ -125,7 +121,6 @@ abstract class HmacSecretKey { /// final key = await HmacSecretKey.generate(Hash.sha256); /// ``` static Future generateKey(Hash hash, {int? length}) { - ArgumentError.checkNotNull(hash, 'hash'); if (length != null && length <= 0) { throw ArgumentError.value(length, 'length', 'must be positive'); } diff --git a/lib/src/webcrypto/webcrypto.pbkdf2.dart b/lib/src/webcrypto/webcrypto.pbkdf2.dart index 6b2a08f6..55629cb0 100644 --- a/lib/src/webcrypto/webcrypto.pbkdf2.dart +++ b/lib/src/webcrypto/webcrypto.pbkdf2.dart @@ -19,8 +19,6 @@ abstract class Pbkdf2SecretKey { Pbkdf2SecretKey._(); // keep the constructor private. static Future importRawKey(List keyData) { - ArgumentError.checkNotNull(keyData, 'keyData'); - return impl.pbkdf2SecretKey_importRawKey(keyData); } diff --git a/lib/src/webcrypto/webcrypto.random.dart b/lib/src/webcrypto/webcrypto.random.dart index ae798125..8b02fd1e 100644 --- a/lib/src/webcrypto/webcrypto.random.dart +++ b/lib/src/webcrypto/webcrypto.random.dart @@ -39,7 +39,6 @@ void fillRandomBytes( // Note: Uint8List and friends all implement TypedData, but dartdoc has a bug // where it's not reporting this. ) { - ArgumentError.checkNotNull(destination, 'destination'); // This limitation is given in the Web Cryptography Specification, see: // https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues if (destination.lengthInBytes > 65536) { diff --git a/lib/src/webcrypto/webcrypto.rsaoaep.dart b/lib/src/webcrypto/webcrypto.rsaoaep.dart index a292288e..a3281f25 100644 --- a/lib/src/webcrypto/webcrypto.rsaoaep.dart +++ b/lib/src/webcrypto/webcrypto.rsaoaep.dart @@ -22,9 +22,6 @@ abstract class RsaOaepPrivateKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaOaepPrivateKey_importPkcs8Key(keyData, hash); } @@ -32,9 +29,6 @@ abstract class RsaOaepPrivateKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaOaepPrivateKey_importJsonWebKey(jwk, hash); } @@ -43,10 +37,6 @@ abstract class RsaOaepPrivateKey { BigInt publicExponent, Hash hash, ) { - ArgumentError.checkNotNull(modulusLength, 'modulusLength'); - ArgumentError.checkNotNull(publicExponent, 'publicExponent'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaOaepPrivateKey_generateKey( modulusLength, publicExponent, @@ -72,9 +62,6 @@ abstract class RsaOaepPublicKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaOaepPublicKey_importSpkiKey(keyData, hash); } @@ -82,9 +69,6 @@ abstract class RsaOaepPublicKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaOaepPublicKey_importJsonWebKey(jwk, hash); } diff --git a/lib/src/webcrypto/webcrypto.rsapss.dart b/lib/src/webcrypto/webcrypto.rsapss.dart index 60843c56..33d0141c 100644 --- a/lib/src/webcrypto/webcrypto.rsapss.dart +++ b/lib/src/webcrypto/webcrypto.rsapss.dart @@ -22,9 +22,6 @@ abstract class RsaPssPrivateKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaPssPrivateKey_importPkcs8Key(keyData, hash); } @@ -32,9 +29,6 @@ abstract class RsaPssPrivateKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaPssPrivateKey_importJsonWebKey(jwk, hash); } @@ -43,10 +37,6 @@ abstract class RsaPssPrivateKey { BigInt publicExponent, Hash hash, ) { - ArgumentError.checkNotNull(modulusLength, 'modulusLength'); - ArgumentError.checkNotNull(publicExponent, 'publicExponent'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaPssPrivateKey_generateKey( modulusLength, publicExponent, @@ -89,9 +79,6 @@ abstract class RsaPssPublicKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaPssPublicKey_importSpkiKey(keyData, hash); } @@ -99,9 +86,6 @@ abstract class RsaPssPublicKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsaPssPublicKey_importJsonWebKey(jwk, hash); } diff --git a/lib/src/webcrypto/webcrypto.rsassapkcs1v15.dart b/lib/src/webcrypto/webcrypto.rsassapkcs1v15.dart index faa8fa15..7b17f847 100644 --- a/lib/src/webcrypto/webcrypto.rsassapkcs1v15.dart +++ b/lib/src/webcrypto/webcrypto.rsassapkcs1v15.dart @@ -64,9 +64,6 @@ abstract class RsassaPkcs1V15PrivateKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsassaPkcs1V15PrivateKey_importPkcs8Key(keyData, hash); } @@ -116,9 +113,6 @@ abstract class RsassaPkcs1V15PrivateKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsassaPkcs1V15PrivateKey_importJsonWebKey(jwk, hash); } @@ -195,10 +189,6 @@ abstract class RsassaPkcs1V15PrivateKey { BigInt publicExponent, Hash hash, ) { - ArgumentError.checkNotNull(modulusLength, 'modulusLength'); - ArgumentError.checkNotNull(publicExponent, 'publicExponent'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsassaPkcs1V15PrivateKey_generateKey( modulusLength, publicExponent, @@ -384,9 +374,6 @@ abstract class RsassaPkcs1V15PublicKey { List keyData, Hash hash, ) { - ArgumentError.checkNotNull(keyData, 'keyData'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsassaPkcs1V15PublicKey_importSpkiKey(keyData, hash); } @@ -436,9 +423,6 @@ abstract class RsassaPkcs1V15PublicKey { Map jwk, Hash hash, ) { - ArgumentError.checkNotNull(jwk, 'jwk'); - ArgumentError.checkNotNull(hash, 'hash'); - return impl.rsassaPkcs1V15PublicKey_importJsonWebKey(jwk, hash); }