export function decodeNonFrameBodyHeader()

in modules/serialize/src/decode_body_header.ts [203:263]


export function decodeNonFrameBodyHeader(
  buffer: Uint8Array,
  headerInfo: HeaderInfo,
  readPos: number
): NonFrameBodyHeader | false {
  /* Precondition: The contentType must be NO_FRAMING. */
  needs(
    ContentType.NO_FRAMING === headerInfo.messageHeader.contentType,
    'Unknown contentType'
  )

  const { ivLength, tagLength } = headerInfo.algorithmSuite

  /* Uint8Array is a view on top of the underlying ArrayBuffer.
   * This means that raw underlying memory stored in the ArrayBuffer
   * may be larger than the Uint8Array.  This is especially true of
   * the Node.js Buffer object.  The offset and length *must* be
   * passed to the DataView otherwise I will get unexpected results.
   */
  const dataView = new DataView(
    buffer.buffer,
    buffer.byteOffset,
    buffer.byteLength
  )

  /* Precondition: decodeNonFrameBodyHeader readPos must be within the byte length of the buffer given. */
  needs(
    dataView.byteLength >= readPos && readPos >= 0,
    'readPos out of bounds.'
  )

  /* Check for early return (Postcondition): There must be enough data to decodeNonFrameBodyHeader.
   * The format expressed here is
   * IVLength: Uint8
   * ContentLength: Uint64
   */
  if (ivLength + 8 + readPos > dataView.byteLength) return false

  const iv = buffer.slice(readPos, (readPos += ivLength))
  const contentLengthBuff = buffer.slice(readPos, (readPos += 8))
  const contentLengthBN = new BN([...contentLengthBuff], 16, 'be')
  // This will throw if the number is larger than Number.MAX_SAFE_INTEGER.
  // i.e. a 53 bit number
  const contentLength = contentLengthBN.toNumber()
  /* Postcondition: Non-framed content length MUST NOT exceed AES-GCM safe limits.
   * https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/data-format/message-body.md#encrypted-content-length
   */
  needs(
    Maximum.BYTES_PER_AES_GCM_NONCE > contentLength,
    'Content length out of bounds.'
  )
  return {
    sequenceNumber: 1,
    iv,
    contentLength,
    readPos,
    tagLength,
    isFinalFrame: true,
    contentType: ContentType.NO_FRAMING,
  }
}