diff --git a/.builder/actions/crt_size_check.py b/.builder/actions/crt_size_check.py index 75bf55262..b9c363a42 100644 --- a/.builder/actions/crt_size_check.py +++ b/.builder/actions/crt_size_check.py @@ -11,7 +11,7 @@ def run(self, env): # Maximum package size (for current platform) in bytes # NOTE: if you increase this, you might also need to increase the # limit in continuous-delivery/pack.sh - max_size = 7_500_000 + max_size = 8_000_000 # size of current folder folder_size = 0 # total size in bytes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0ce72ae3..822570f71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,7 @@ jobs: check-docs: runs-on: ubuntu-20.04 # latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Check docs @@ -179,7 +179,7 @@ jobs: runs-on: ubuntu-20.04 # latest steps: - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -191,7 +191,7 @@ jobs: check-lockfile-version: runs-on: ubuntu-20.04 # latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check for edits to package-lock.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 30224fa1b..8c23e5dba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.9) project(aws-crt-nodejs C) option(BUILD_DEPS "Builds aws common runtime dependencies as part of build, only do this if you don't want to control your dependency chain." ON) @@ -45,7 +45,7 @@ if (BUILD_DEPS) if (UNIX AND NOT APPLE) include(AwsPrebuildDependency) # s2n-tls uses libcrypto during its configuration, so we need to prebuild aws-lc. - prebuild_dependency( + aws_prebuild_dependency( DEPENDENCY_NAME AWSLC SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/crt/aws-lc CMAKE_ARGUMENTS @@ -54,8 +54,14 @@ if (BUILD_DEPS) -DBUILD_LIBSSL=OFF -DBUILD_TESTING=OFF ) - set(UNSAFE_TREAT_WARNINGS_AS_ERRORS OFF) - add_subdirectory(crt/s2n) + # prebuild s2n-tls. + aws_prebuild_dependency( + DEPENDENCY_NAME S2N + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/crt/s2n + CMAKE_ARGUMENTS + -DUNSAFE_TREAT_WARNINGS_AS_ERRORS=OFF + -DBUILD_TESTING=OFF + ) endif() add_subdirectory(crt/aws-c-sdkutils) @@ -74,10 +80,6 @@ else() set(IN_SOURCE_BUILD OFF) endif() -if (POLICY CMP0069) - cmake_policy(SET CMP0069 NEW) # Enable LTO/IPO if available in the compiler, see AwsCFlags -endif() - list(APPEND CMAKE_MODULE_PATH "${CMAKE_PREFIX_PATH}/${CMAKE_INSTALL_LIBDIR}/cmake") include(AwsCFlags) diff --git a/continuous-delivery/pack.sh b/continuous-delivery/pack.sh index 5512dd64b..15e1fb5e3 100644 --- a/continuous-delivery/pack.sh +++ b/continuous-delivery/pack.sh @@ -39,7 +39,7 @@ mkdir $UNZIP tar -xf aws-crt-$CURRENT_TAG.tgz -C $UNZIP PACK_FILE_SIZE_KB=$(du -sk $UNZIP | awk '{print $1}') echo "Current package size: ${PACK_FILE_SIZE_KB}" -if expr $PACK_FILE_SIZE_KB \> "$((25000))" ; then +if expr $PACK_FILE_SIZE_KB \> "$((26000))" ; then # the package size is too large, return -1 echo "Package size is too large!" exit -1 diff --git a/crt/aws-c-auth b/crt/aws-c-auth index 53a31bacf..3982bd75f 160000 --- a/crt/aws-c-auth +++ b/crt/aws-c-auth @@ -1 +1 @@ -Subproject commit 53a31bacf2918e848e00b052d2e25cba0be069d9 +Subproject commit 3982bd75fea74efd8f9b462b27fedd4599db4f53 diff --git a/crt/aws-c-cal b/crt/aws-c-cal index 77ca3aea8..656762aef 160000 --- a/crt/aws-c-cal +++ b/crt/aws-c-cal @@ -1 +1 @@ -Subproject commit 77ca3aea879bc768082fe7ec715adcde8e98c332 +Subproject commit 656762aefbee2bc8f509cb23cd107abff20a72bb diff --git a/crt/aws-c-common b/crt/aws-c-common index 8419fe707..f41b772f0 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 8419fe7077778b5ca40e8822f969665bbddc226c +Subproject commit f41b772f0de9454a4e7a65750b58c2379533bbf1 diff --git a/crt/aws-c-compression b/crt/aws-c-compression index ea1d421a4..c6c1191e5 160000 --- a/crt/aws-c-compression +++ b/crt/aws-c-compression @@ -1 +1 @@ -Subproject commit ea1d421a421ad83a540309a94c38d50b6a5d836b +Subproject commit c6c1191e525e5aa6ead9e1afc392e35d3b50331e diff --git a/crt/aws-c-event-stream b/crt/aws-c-event-stream index 1a70c50f7..d2dcc9344 160000 --- a/crt/aws-c-event-stream +++ b/crt/aws-c-event-stream @@ -1 +1 @@ -Subproject commit 1a70c50f78a6e706f1f91a4ed138478271b6d9d3 +Subproject commit d2dcc9344dae24de320866045d85166d8a91a0d1 diff --git a/crt/aws-c-http b/crt/aws-c-http index d83f8d701..74b3a0dd1 160000 --- a/crt/aws-c-http +++ b/crt/aws-c-http @@ -1 +1 @@ -Subproject commit d83f8d70143ddce5ab4e479175fbd44ba994211b +Subproject commit 74b3a0dd1396b72f701c8bdf24e5c6f41e52cf87 diff --git a/crt/aws-c-io b/crt/aws-c-io index 878b4fa02..fe93d0afc 160000 --- a/crt/aws-c-io +++ b/crt/aws-c-io @@ -1 +1 @@ -Subproject commit 878b4fa027bda4041493f06e0562d5e98bb3deb8 +Subproject commit fe93d0afcc1cede32ac9569abd8669ed011b1b8c diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index ed7bbd68c..627c3334e 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit ed7bbd68c03d7022c915a2924740ab7992ad2311 +Subproject commit 627c3334e52021aa8d5772b6ca076884610f3219 diff --git a/crt/aws-c-sdkutils b/crt/aws-c-sdkutils index 8c7af71f9..0818f28ee 160000 --- a/crt/aws-c-sdkutils +++ b/crt/aws-c-sdkutils @@ -1 +1 @@ -Subproject commit 8c7af71f91ed5b9d2a043d51f120495f43723f80 +Subproject commit 0818f28ee436b892f09fbe8e3a6ae37ff40e9436 diff --git a/crt/aws-checksums b/crt/aws-checksums index aac442a2d..0d2f5521f 160000 --- a/crt/aws-checksums +++ b/crt/aws-checksums @@ -1 +1 @@ -Subproject commit aac442a2dbbb5e72d0a3eca8313cf65e7e1cac2f +Subproject commit 0d2f5521f61215f38f791d106ae304402208112d diff --git a/crt/aws-lc b/crt/aws-lc index 4e54dd836..8ffe277c2 160000 --- a/crt/aws-lc +++ b/crt/aws-lc @@ -1 +1 @@ -Subproject commit 4e54dd8363396f257d7a2317c48101e18170e6fb +Subproject commit 8ffe277c21915ca82dc78a3bdc6a92e10c284b92 diff --git a/crt/s2n b/crt/s2n index 114ccab0f..ffe0bf42d 160000 --- a/crt/s2n +++ b/crt/s2n @@ -1 +1 @@ -Subproject commit 114ccab0ff2cde491203ac841837d0d39b767412 +Subproject commit ffe0bf42da8f139eff8fd2237f47fbde40b478fb diff --git a/lib/browser/crypto.ts b/lib/browser/crypto.ts index 0c8a39af2..c537fae86 100644 --- a/lib/browser/crypto.ts +++ b/lib/browser/crypto.ts @@ -12,25 +12,35 @@ */ import * as Crypto from "crypto-js"; -import { fromUtf8 } from "@aws-sdk/util-utf8-browser"; import { Hashable } from "../common/crypto"; export { Hashable } from "../common/crypto"; /** - * Object that allows for continuous MD5 hashing of data. - * - * @category Crypto + * CryptoJS does not provide easy access to underlying bytes. + * As a workaround just dump it to a string and then reinterpret chars as individual bytes. + * Note: we are using Latin1 here because its a static sized 8 bit encoding so each char maps directly to a byte value. + * TODO: long term we would probably want to move to WebCrypto for SHA's and some other 3p for crc's and md5. + * @param hash + * @returns */ -export class Md5Hash { - private hash?: Crypto.WordArray; +function wordArrayToUint8Array(hash: Crypto.WordArray) { + return Uint8Array.from(hash.toString(Crypto.enc.Latin1).split('').map(c => c.charCodeAt(0)));; +} + +class BaseHash { + private hasher : any; + + constructor(hasher: any) { + this.hasher = hasher; + } /** * Hashes additional data * @param data Additional data to hash */ update(data: Hashable) { - this.hash = Crypto.MD5(data.toString(), this.hash ? this.hash.toString() : undefined); + this.hasher.update(data.toString()); } /** @@ -41,10 +51,20 @@ export class Md5Hash { * @returns the final hash digest */ finalize(truncate_to?: number): DataView { - const digest = this.hash ? this.hash.toString() : ''; - const truncated = digest.substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); + const hashBuffer = wordArrayToUint8Array(this.hasher.finalize()) ; + const truncated = hashBuffer.slice(0, truncate_to ? truncate_to : hashBuffer.length); + return new DataView(truncated.buffer);; + } +} + +/** + * Object that allows for continuous MD5 hashing of data. + * + * @category Crypto + */ +export class Md5Hash extends BaseHash { + constructor() { + super(Crypto.algo.MD5.create()); } } @@ -71,29 +91,9 @@ export function hash_md5(data: Hashable, truncate_to?: number): DataView { * * @category Crypto */ -export class Sha256Hash { - private hash?: Crypto.WordArray; - - /** - * Hashes additional data - * @param data Additional data to hash - */ - update(data: Hashable) { - this.hash = Crypto.SHA256(data.toString(), this.hash ? this.hash.toString() : undefined); - } - - /** - * Completes the hash computation and returns the final hash digest. - * - * @param truncate_to The maximum number of bytes to receive. Leave as undefined or 0 to receive the entire digest. - * - * @returns the final hash digest - */ - finalize(truncate_to?: number): DataView { - const digest = this.hash ? this.hash.toString() : ''; - const truncated = digest.substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); +export class Sha256Hash extends BaseHash { + constructor() { + super(Crypto.algo.SHA256.create()); } } @@ -109,10 +109,9 @@ export class Sha256Hash { * @category Crypto */ export function hash_sha256(data: Hashable, truncate_to?: number): DataView { - const digest = Crypto.SHA256(data.toString()).toString(); - const truncated = digest.substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); + const sha256 = new Sha256Hash(); + sha256.update(data); + return sha256.finalize(truncate_to); } /** @@ -120,29 +119,9 @@ export function hash_sha256(data: Hashable, truncate_to?: number): DataView { * * @category Crypto */ - export class Sha1Hash { - private hash?: Crypto.WordArray; - - /** - * Hashes additional data - * @param data Additional data to hash - */ - update(data: Hashable) { - this.hash = Crypto.SHA1(data.toString(), this.hash ? this.hash.toString() : undefined); - } - - /** - * Completes the hash computation and returns the final hash digest. - * - * @param truncate_to The maximum number of bytes to receive. Leave as undefined or 0 to receive the entire digest. - * - * @returns the final hash digest - */ - finalize(truncate_to?: number): DataView { - const digest = this.hash ? this.hash.toString() : ''; - const truncated = digest.substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); + export class Sha1Hash extends BaseHash { + constructor() { + super(Crypto.algo.SHA1.create()); } } @@ -158,10 +137,9 @@ export function hash_sha256(data: Hashable, truncate_to?: number): DataView { * @category Crypto */ export function hash_sha1(data: Hashable, truncate_to?: number): DataView { - const digest = Crypto.SHA1(data.toString()).toString(); - const truncated = digest.substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); + const sha1 = new Sha1Hash(); + sha1.update(data); + return sha1.finalize(truncate_to); } /** @@ -169,38 +147,14 @@ export function hash_sha1(data: Hashable, truncate_to?: number): DataView { * * @category Crypto */ -export class Sha256Hmac { - private hmac: any; - +export class Sha256Hmac extends BaseHash { /** * Constructor for the Sha256Hmac class type * @param secret secret key to seed the hmac process with */ constructor(secret: Hashable) { // @ts-ignore types file doesn't have this signature of create() - this.hmac = Crypto.algo.HMAC.create(Crypto.algo.SHA256, secret); - } - - /** - * Hashes additional data - * @param data Additional data to hash - */ - update(data: Hashable) { - this.hmac.update(data.toString()); - } - - /** - * Completes the hash computation and returns the final hmac digest. - * - * @param truncate_to The maximum number of bytes to receive. Leave as undefined or 0 to receive the entire digest. - * - * @returns the final hmac digest - */ - finalize(truncate_to?: number): DataView { - const digest = this.hmac.finalize(); - const truncated = digest.toString().substring(0, truncate_to ? truncate_to : digest.length); - const bytes = fromUtf8(truncated); - return new DataView(bytes.buffer); + super(Crypto.algo.HMAC.create(Crypto.algo.SHA256, secret)); } } diff --git a/lib/native/binding.d.ts b/lib/native/binding.d.ts index 6e0a8455b..ca86f0ced 100644 --- a/lib/native/binding.d.ts +++ b/lib/native/binding.d.ts @@ -142,6 +142,8 @@ export function hmac_sha256_compute(secret: StringLike, data: StringLike, trunca export function checksums_crc32(data: StringLike, previous?: number): number; /** @internal */ export function checksums_crc32c(data: StringLike, previous?: number): number; +/** @internal */ +export function checksums_crc64nvme(data: StringLike, previous?: DataView): DataView; /* MQTT5 Client */ diff --git a/lib/native/checksums.spec.ts b/lib/native/checksums.spec.ts index 6cf0356e8..2676ed49d 100644 --- a/lib/native/checksums.spec.ts +++ b/lib/native/checksums.spec.ts @@ -81,4 +81,21 @@ test('crc32c_large_buffer', () => { const output = checksums.crc32c(arr); const expected = 0xfb5b991d expect(output).toEqual(expected); -}); \ No newline at end of file +}); + +test('crc64nvme_zeros_one_shot', () => { + const arr = new Uint8Array(32); + const output = checksums.crc64nvme(arr); + expect(output.getBigUint64(0)).toEqual(BigInt("0xCF3473434D4ECF3B")); +}); + +test('crc64nvme_zeros_iterated', () => { + const buffer = new ArrayBuffer(8); + let previous = new DataView(buffer); + previous.setBigUint64(0, BigInt(0)); + + for (let i = 0; i < 32; i++) { + previous = checksums.crc64nvme(new Uint8Array(1), previous); + } + expect(previous.getBigUint64(0)).toEqual(BigInt("0xCF3473434D4ECF3B")); +}); diff --git a/lib/native/checksums.ts b/lib/native/checksums.ts index 218047078..16f57c63b 100644 --- a/lib/native/checksums.ts +++ b/lib/native/checksums.ts @@ -38,4 +38,16 @@ export function crc32(data: Hashable, previous?: number): number { */ export function crc32c(data: Hashable, previous?: number): number { return crt_native.checksums_crc32c(data, previous); -} \ No newline at end of file +} + +/** + * Computes a crc64nvme checksum. + * + * @param data The data to checksum + * @param previous previous crc64nvme checksum result. Used if you are buffering large input. + * + * @category Crypto + */ +export function crc64nvme(data: Hashable, previous?: DataView): DataView { + return crt_native.checksums_crc64nvme(data, previous); +} diff --git a/lib/native/crypto.spec.ts b/lib/native/crypto.spec.ts index 33a5123c0..51f40cba9 100644 --- a/lib/native/crypto.spec.ts +++ b/lib/native/crypto.spec.ts @@ -5,6 +5,7 @@ import * as native from './crypto'; import * as browser from '../browser/crypto'; +import '@test/custom_matchers' test('md5 multi-part matches', () => { const parts = ['ABC', '123', 'XYZ']; @@ -17,7 +18,7 @@ test('md5 multi-part matches', () => { const native_hash = native_md5.finalize(); const browser_hash = browser_md5.finalize(); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('md5 one-shot matches', () => { @@ -25,7 +26,7 @@ test('md5 one-shot matches', () => { const native_hash = native.hash_md5(data); const browser_hash = browser.hash_md5(data); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('SHA256 multi-part matches', () => { @@ -39,7 +40,7 @@ test('SHA256 multi-part matches', () => { const native_hash = native_sha.finalize(); const browser_hash = browser_sha.finalize(); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('SHA256 one-shot matches', () => { @@ -47,7 +48,7 @@ test('SHA256 one-shot matches', () => { const native_hash = native.hash_sha256(data); const browser_hash = browser.hash_sha256(data); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('SHA1 multi-part matches', () => { @@ -61,7 +62,7 @@ test('SHA1 multi-part matches', () => { const native_hash = native_sha.finalize(); const browser_hash = browser_sha.finalize(); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('SHA1 one-shot matches', () => { @@ -69,7 +70,7 @@ test('SHA1 one-shot matches', () => { const native_hash = native.hash_sha1(data); const browser_hash = browser.hash_sha1(data); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('hmac-256 multi-part matches', () => { @@ -84,7 +85,7 @@ test('hmac-256 multi-part matches', () => { const native_hash = native_hmac.finalize(); const browser_hash = browser_hmac.finalize(); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); test('hmac-256 one-shot matches', () => { @@ -93,5 +94,5 @@ test('hmac-256 one-shot matches', () => { const native_hash = native.hmac_sha256(secret, data); const browser_hash = browser.hmac_sha256(secret, data); - expect(native_hash).toEqual(browser_hash); + expect(native_hash).toEqualDataView(browser_hash); }); diff --git a/lib/native/crypto.ts b/lib/native/crypto.ts index f64134132..c05bc0d65 100644 --- a/lib/native/crypto.ts +++ b/lib/native/crypto.ts @@ -105,7 +105,6 @@ export function hash_sha256(data: Hashable, truncate_to?: number): DataView { } } - /** * Computes an SHA1 hash. Use this if you don't need to stream the data you're hashing and can load the entire input * into memory. diff --git a/package-lock.json b/package-lock.json index d45723268..22d9858d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -299,12 +299,12 @@ } }, "@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/plugin-syntax-import-meta": { @@ -398,12 +398,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" } }, "@babel/runtime": { @@ -932,9 +932,9 @@ "dev": true }, "@types/uuid": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.13.tgz", - "integrity": "sha512-pAeZeUbLE4Z9Vi9wsWV2bYPTweEHeJJy0G4pEjOA/FSvy1Ad5U5Km8iDV6TKre1mjBiVNfAdVHKruP8bAh4Q5A==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true }, "@types/ws": { @@ -1429,9 +1429,9 @@ "dev": true }, "cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true }, "cliui": { @@ -2398,9 +2398,9 @@ "dev": true }, "is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "requires": { "hasown": "^2.0.2" @@ -2501,7 +2501,8 @@ "isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "requires": {} }, "istanbul-lib-coverage": { "version": "3.2.2", @@ -2571,60 +2572,6 @@ "@jest/core": "^27.5.1", "import-local": "^3.0.2", "jest-cli": "^27.5.1" - }, - "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } } }, "jest-changed-files": { @@ -2665,6 +2612,60 @@ "throat": "^6.0.1" } }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, "jest-config": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", @@ -2901,7 +2902,8 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true + "dev": true, + "requires": {} }, "jest-puppeteer": { "version": "5.0.4", @@ -3080,12 +3082,6 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true } } }, @@ -3216,7 +3212,8 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -3275,6 +3272,12 @@ "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", "dev": true }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3666,9 +3669,9 @@ } }, "nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true }, "once": { @@ -3915,7 +3918,8 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -4252,6 +4256,21 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -4273,21 +4292,6 @@ "strip-ansi": "^6.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4600,7 +4604,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/typedoc-plugin-merge-modules/-/typedoc-plugin-merge-modules-5.1.0.tgz", "integrity": "sha512-jXH27L/wlxFjErgBXleh3opVgjVTXFEuBo68Yfl18S9Oh/IqxK6NV94jlEJ9hl4TXc9Zm2l7Rfk41CEkcCyvFQ==", - "dev": true + "dev": true, + "requires": {} }, "typescript": { "version": "4.9.5", @@ -4696,9 +4701,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "dev": true }, "v8-to-istanbul": { @@ -4977,7 +4982,8 @@ "ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "requires": {} }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index 7042149a6..d7c4e6666 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@types/node": "^14.18.63", "@types/prettier": "2.6.0", "@types/puppeteer": "^5.4.7", - "@types/uuid": "^3.4.13", + "@types/uuid": "^10.0.0", "@types/ws": "^7.4.7", "aws-sdk": "^2.1537.0", "cmake-js": "^7.3.0", @@ -45,7 +45,7 @@ "typedoc": "^0.24.8", "typedoc-plugin-merge-modules": "^5.1.0", "typescript": "^4.9.5", - "uuid": "^8.3.2", + "uuid": "^10.0.0", "yargs": "^17.2.1" }, "dependencies": { diff --git a/source/checksums.c b/source/checksums.c index 05c930f23..40f166726 100644 --- a/source/checksums.c +++ b/source/checksums.c @@ -6,17 +6,21 @@ #include "checksums.h" #include +#include -napi_value crc_common(napi_env env, napi_callback_info info, uint32_t (*checksum_fn)(const uint8_t *, int, uint32_t)) { +napi_value crc32_common( + napi_env env, + napi_callback_info info, + uint32_t (*checksum_fn)(const uint8_t *, size_t, uint32_t)) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); struct aws_byte_buf to_hash; AWS_ZERO_STRUCT(to_hash); - // struct aws_byte_buf *to_hash_ptr = (struct aws_byte_buf*)NULL; + napi_value node_val = NULL; if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); goto done; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -30,22 +34,16 @@ napi_value crc_common(napi_env env, napi_callback_info info, uint32_t (*checksum } uint8_t *buffer = to_hash.buffer; size_t length = to_hash.len; - uint32_t previous = 0; + uint32_t previous_crc = 0; if (!aws_napi_is_null_or_undefined(env, node_args[1])) { - if (napi_get_value_uint32(env, node_args[1], &previous)) { - napi_throw_type_error(env, NULL, "previous argument must be undefined or a positive number"); + if (napi_get_value_uint32(env, node_args[1], &previous_crc)) { + napi_throw_type_error(env, NULL, "previous_crc argument must be undefined or a positive number"); goto done; } } - uint32_t val = previous; - while (length > INT_MAX) { - val = checksum_fn(buffer, INT_MAX, val); - buffer += (size_t)INT_MAX; - length -= (size_t)INT_MAX; - } - val = checksum_fn(buffer, (int)length, val); + uint32_t val = checksum_fn(buffer, length, previous_crc); AWS_NAPI_CALL(env, napi_create_uint32(env, val, &node_val), { goto done; }); done: @@ -55,9 +53,72 @@ napi_value crc_common(napi_env env, napi_callback_info info, uint32_t (*checksum } napi_value aws_napi_checksums_crc32(napi_env env, napi_callback_info info) { - return crc_common(env, info, aws_checksums_crc32); + return crc32_common(env, info, aws_checksums_crc32_ex); } napi_value aws_napi_checksums_crc32c(napi_env env, napi_callback_info info) { - return crc_common(env, info, aws_checksums_crc32c); + return crc32_common(env, info, aws_checksums_crc32c_ex); +} + +napi_value aws_napi_checksums_crc64nvme(napi_env env, napi_callback_info info) { + napi_value node_args[2]; + size_t num_args = AWS_ARRAY_SIZE(node_args); + struct aws_byte_buf to_hash; + AWS_ZERO_STRUCT(to_hash); + struct aws_byte_buf previous_crc_buf; + AWS_ZERO_STRUCT(previous_crc_buf); + + napi_value node_val = NULL; + + if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { + napi_throw_error(env, NULL, "Failed to retrieve callback information"); + goto done; + } + if (num_args != AWS_ARRAY_SIZE(node_args)) { + napi_throw_error(env, NULL, "aws_napi_checksums_crc64 needs exactly 2 arguments"); + goto done; + } + + if (aws_byte_buf_init_from_napi(&to_hash, env, node_args[0])) { + napi_throw_type_error(env, NULL, "to_hash argument must be a string or array"); + goto done; + } + uint8_t *buffer = to_hash.buffer; + size_t length = to_hash.len; + + uint64_t previous_crc = 0; + if (!aws_napi_is_null_or_undefined(env, node_args[1])) { + if (aws_byte_buf_init_from_napi(&previous_crc_buf, env, node_args[1])) { + napi_throw_type_error(env, NULL, "previous_crc argument must be undefined or a DataView over 8 bytes"); + goto done; + } + if (previous_crc_buf.len != 8) { + napi_throw_type_error(env, NULL, "previous_crc argument must be a DataView over 8 bytes"); + goto done; + } + previous_crc = aws_read_u64(previous_crc_buf.buffer); + } + + uint64_t val = aws_checksums_crc64nvme_ex(buffer, length, previous_crc); + + napi_value arraybuffer; + void *data = NULL; + if (napi_create_arraybuffer(env, 8, &data, &arraybuffer)) { + napi_throw_error(env, NULL, "Failed to create output arraybuffer"); + goto done; + } + + struct aws_byte_buf out_buf = aws_byte_buf_from_empty_array(data, 8); + aws_byte_buf_write_be64(&out_buf, val); + + if (napi_create_dataview(env, 8, arraybuffer, 0, &node_val)) { + napi_throw_error(env, NULL, "Failed to create output dataview"); + goto done; + } + +done: + aws_byte_buf_clean_up(&to_hash); + aws_byte_buf_clean_up(&previous_crc_buf); + + return node_val; } diff --git a/source/checksums.h b/source/checksums.h index 156ee73f0..2fbba3fb1 100644 --- a/source/checksums.h +++ b/source/checksums.h @@ -9,5 +9,6 @@ napi_value aws_napi_checksums_crc32(napi_env env, napi_callback_info info); napi_value aws_napi_checksums_crc32c(napi_env env, napi_callback_info info); +napi_value aws_napi_checksums_crc64nvme(napi_env env, napi_callback_info info); #endif /* AWS_CRT_NODEJS_CHECKSUMS_H */ diff --git a/source/crypto.c b/source/crypto.c index 2fef256c0..bec9fdf06 100644 --- a/source/crypto.c +++ b/source/crypto.c @@ -79,7 +79,7 @@ napi_value aws_napi_hash_update(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -114,7 +114,7 @@ napi_value aws_napi_hash_digest(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -169,7 +169,7 @@ napi_value aws_napi_hash_md5_compute(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -226,7 +226,7 @@ napi_value aws_napi_hash_sha256_compute(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -240,7 +240,7 @@ napi_value aws_napi_hash_sha256_compute(napi_env env, napi_callback_info info) { return NULL; } - size_t digest_size = AWS_MD5_LEN; + size_t digest_size = AWS_SHA256_LEN; if (!aws_napi_is_null_or_undefined(env, node_args[1])) { uint32_t truncate_to = 0; @@ -297,7 +297,7 @@ napi_value aws_napi_hash_sha1_compute(napi_env env, napi_callback_info info) { return NULL; } - size_t digest_size = AWS_MD5_LEN; + size_t digest_size = AWS_SHA1_LEN; if (!aws_napi_is_null_or_undefined(env, node_args[1])) { uint32_t truncate_to = 0; @@ -359,7 +359,7 @@ napi_value aws_napi_hmac_sha256_new(napi_env env, napi_callback_info info) { napi_value node_args[1]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -394,7 +394,7 @@ napi_value aws_napi_hmac_update(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -429,7 +429,7 @@ napi_value aws_napi_hmac_digest(napi_env env, napi_callback_info info) { napi_value node_args[2]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -484,7 +484,7 @@ napi_value aws_napi_hmac_sha256_compute(napi_env env, napi_callback_info info) { napi_value node_args[3]; size_t num_args = AWS_ARRAY_SIZE(node_args); if (napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) { - napi_throw_error(env, NULL, "Failed to retreive callback information"); + napi_throw_error(env, NULL, "Failed to retrieve callback information"); return NULL; } if (num_args != AWS_ARRAY_SIZE(node_args)) { @@ -505,7 +505,7 @@ napi_value aws_napi_hmac_sha256_compute(napi_env env, napi_callback_info info) { return NULL; } - size_t digest_size = AWS_MD5_LEN; + size_t digest_size = AWS_SHA256_LEN; if (!aws_napi_is_null_or_undefined(env, node_args[2])) { uint32_t truncate_to = 0; diff --git a/source/io.c b/source/io.c index 8661a4cee..f5aafd6f1 100644 --- a/source/io.c +++ b/source/io.c @@ -770,6 +770,7 @@ napi_value aws_napi_io_socket_options_new(napi_env env, napi_callback_info info) } struct aws_socket_options options; + AWS_ZERO_STRUCT(options); uint32_t enum_value = 0; if (napi_get_value_uint32(env, node_args[0], &enum_value) || enum_value > AWS_SOCKET_DGRAM) { diff --git a/source/module.c b/source/module.c index 656314cf2..ba7e4603a 100644 --- a/source/module.c +++ b/source/module.c @@ -1411,6 +1411,7 @@ static bool s_create_and_register_function( /* Checksums */ CREATE_AND_REGISTER_FN(checksums_crc32) CREATE_AND_REGISTER_FN(checksums_crc32c) + CREATE_AND_REGISTER_FN(checksums_crc64nvme) /* HTTP */ CREATE_AND_REGISTER_FN(http_proxy_options_new) diff --git a/test/custom_matchers.ts b/test/custom_matchers.ts new file mode 100644 index 000000000..73ee75589 --- /dev/null +++ b/test/custom_matchers.ts @@ -0,0 +1,46 @@ +import { expect } from "@jest/globals"; + +/* + * Note: jest by default does not compare contents of complex classes like DataView. + * So when comparing two data views for equality we equality we always end up with true result because + * the only thing compared is the type of the instance. + * So add a custom comparison operation for it. + * Its possible to make it global for all tests with some additional work. + * Jest 30 is adding DataView equivalence checks out of the box. +*/ + +declare global { + namespace jest { + interface Matchers { + toEqualDataView(expected: DataView): R; + } + } +} + +expect.extend({ + toEqualDataView(actual: DataView, expected: DataView) { + let dv_actual = actual as DataView; + let dv_expected = expected as DataView; + + if (dv_actual.buffer.byteLength !== dv_expected.buffer.byteLength) { + return { + message: () => 'DataViews of different length; actual: ${dv1.buffer.byteLength}, expected: ${dv2.buffer.byteLength}', + pass: false + }; + } + + for (let i = 0; i < dv_actual.buffer.byteLength; i++) { + if (dv_actual.getUint8(i) !== dv_expected.getUint8(i)) { + return { + message: () => 'DataViews byte mismatch at index ${i}; actual: ${dv_actual.getUint8(i)}, expected: ${dv_expected.getUint8(i)}', + pass: false + }; + } + } + + return { + message: () => 'DataViews are equal', + pass: true + }; + }, +}); diff --git a/test/native/jest.setup.ts b/test/native/jest.setup.ts index 8b1378917..e69de29bb 100644 --- a/test/native/jest.setup.ts +++ b/test/native/jest.setup.ts @@ -1 +0,0 @@ -