diff --git a/lib/src/nanotdf/models/Policy/AbstractPolicy.ts b/lib/src/nanotdf/models/Policy/AbstractPolicy.ts index a9417d44..ee6c9648 100644 --- a/lib/src/nanotdf/models/Policy/AbstractPolicy.ts +++ b/lib/src/nanotdf/models/Policy/AbstractPolicy.ts @@ -9,6 +9,8 @@ abstract class AbstractPolicy implements PolicyInterface { static readonly BODY_BYTE_MAX_LEN = 257; static readonly BINDING_BYTE_MIN_LEN = 8; static readonly BINDING_BYTE_MAX_LEN = 132; + static readonly SIZE_OF_LENGTH_FIELD = 1; // 1 byte for each length field (R and S) + static readonly GMAC_BINDING_LEN = 8; readonly type: PolicyType; readonly binding: Uint8Array; @@ -18,7 +20,7 @@ abstract class AbstractPolicy implements PolicyInterface { // eslint-disable-next-line @typescript-eslint/no-unused-vars buff: Uint8Array, // eslint-disable-next-line @typescript-eslint/no-unused-vars - bindingLength: number, + useECDSABinding: boolean, // eslint-disable-next-line @typescript-eslint/no-unused-vars type?: PolicyType ): { policy: PolicyInterface; offset: number } { @@ -43,6 +45,40 @@ abstract class AbstractPolicy implements PolicyInterface { toBuffer(): Uint8Array | never { throw new Error('toBuffer() was not implemented'); } + +/** + * Parses an ECDSA binding from a given buffer. + * + * @param {Uint8Array} buff - The buffer containing the ECDSA binding. + * @returns {{ bindingLength: number; binding: Uint8Array }} - An object containing the binding length and the binding subarray. + */ + static parseECDSABinding(buff: Uint8Array): { bindingLength: number; binding: Uint8Array } { + const lengthOfR = buff[0]; + const lengthOfS = buff[this.SIZE_OF_LENGTH_FIELD + lengthOfR]; + + const bindingLength = this.SIZE_OF_LENGTH_FIELD + lengthOfR + this.SIZE_OF_LENGTH_FIELD + lengthOfS; + const binding = buff.subarray(0, bindingLength); + + return { bindingLength, binding }; + } + +/** + * Parses a binding from a given buffer based on the specified binding type. + * + * @param {Uint8Array} buff - The buffer containing the binding. + * @param {boolean} useEcdsaBinding - Flag indicating whether to use ECDSA binding. + * @param {number} offset - The starting offset in the buffer. + * @returns {{ binding: Uint8Array; newOffset: number }} - An object containing the binding and the new offset. + */ + static parseBinding(buff: Uint8Array, useEcdsaBinding: boolean, offset: number): { binding: Uint8Array; newOffset: number } { + if (useEcdsaBinding) { + const ecdsaBinding = this.parseECDSABinding(buff.subarray(offset)); + return { binding: ecdsaBinding.binding, newOffset: offset + ecdsaBinding.bindingLength }; + } else { + const binding = buff.subarray(offset, offset + this.GMAC_BINDING_LEN); + return { binding, newOffset: offset + this.GMAC_BINDING_LEN }; + } + } } export default AbstractPolicy; diff --git a/lib/src/nanotdf/models/Policy/EmbeddedPolicy.ts b/lib/src/nanotdf/models/Policy/EmbeddedPolicy.ts index e0a9dca9..92f4b649 100644 --- a/lib/src/nanotdf/models/Policy/EmbeddedPolicy.ts +++ b/lib/src/nanotdf/models/Policy/EmbeddedPolicy.ts @@ -19,7 +19,7 @@ class EmbeddedPolicy extends AbstractPolicy implements EmbeddedPolicyInterface { static override parse( buff: Uint8Array, - bindingLength: number, + useEcdsaBinding: boolean, type: PolicyTypes ): { offset: number; policy: EmbeddedPolicy } { let offset = 0; @@ -32,8 +32,8 @@ class EmbeddedPolicy extends AbstractPolicy implements EmbeddedPolicyInterface { const content = buff.subarray(offset, offset + length); offset += length; - const binding = buff.subarray(offset, offset + bindingLength); - offset += bindingLength; + const { binding, newOffset: bindingOffset } = this.parseBinding(buff, useEcdsaBinding, offset); + offset = bindingOffset; return { policy: new EmbeddedPolicy(type, binding, content), diff --git a/lib/src/nanotdf/models/Policy/PolicyFactory.ts b/lib/src/nanotdf/models/Policy/PolicyFactory.ts index e8c51cde..6c67e3b3 100644 --- a/lib/src/nanotdf/models/Policy/PolicyFactory.ts +++ b/lib/src/nanotdf/models/Policy/PolicyFactory.ts @@ -2,7 +2,6 @@ import AbstractPolicy from './AbstractPolicy.js'; import EmbeddedPolicy from './EmbeddedPolicy.js'; import RemotePolicy from './RemotePolicy.js'; import PolicyTypeEnum from '../../enum/PolicyTypeEnum.js'; -import { lengthOfBinding } from '../../helpers/calculateByCipher.js'; import { InvalidPolicyTypeError } from '../../../errors.js'; import CurveNameEnum from '../../enum/CurveNameEnum.js'; @@ -12,7 +11,6 @@ function parse( curve: CurveNameEnum ): { policy: AbstractPolicy; offset: number } | never { const type = buff[AbstractPolicy.TYPE_BYTE_OFF]; - const bindingLength = lengthOfBinding(useEcdsaBinding, curve); let policy: AbstractPolicy; let offset: number; @@ -20,7 +18,7 @@ function parse( if (type === PolicyTypeEnum.Remote) { ({ policy, offset } = RemotePolicy.parse( buff.subarray(AbstractPolicy.TYPE_BYTE_LEN), - bindingLength + useEcdsaBinding, )); } else if ( [ @@ -32,7 +30,7 @@ function parse( ) { ({ policy, offset } = EmbeddedPolicy.parse( buff.subarray(AbstractPolicy.TYPE_BYTE_LEN), - bindingLength, + useEcdsaBinding, type )); } else { diff --git a/lib/src/nanotdf/models/Policy/RemotePolicy.ts b/lib/src/nanotdf/models/Policy/RemotePolicy.ts index c6ab1f80..a181e8cf 100644 --- a/lib/src/nanotdf/models/Policy/RemotePolicy.ts +++ b/lib/src/nanotdf/models/Policy/RemotePolicy.ts @@ -15,14 +15,14 @@ class RemotePolicy extends AbstractPolicy implements RemotePolicyInterface { static override parse( buff: Uint8Array, - bindingLength: number + useEcdsaBinding: boolean ): { offset: number; policy: RemotePolicy } { let offset = 0; const resource = new ResourceLocator(buff); offset += resource.offset; - const binding = buff.subarray(offset, offset + bindingLength); - offset += bindingLength; + const { binding, newOffset: bindingOffset } = this.parseBinding(buff, useEcdsaBinding, offset); + offset = bindingOffset; return { policy: new RemotePolicy(PolicyTypeEnum.Remote, binding, resource),