nist_keywrap16(const void *ctx, nettle_cipher_func *encrypt,
               const uint8_t *iv, size_t ciphertext_length,
               uint8_t *ciphertext, const uint8_t *cleartext) {
  uint8_t * R = NULL, A[8] = {0}, I[16] = {0}, B[16] = {0};
  uint64_t A64;
  size_t i, j, n;

  if ((R = o_malloc(ciphertext_length-8)) == NULL)
    return;

  n = (ciphertext_length-8)/8;
  memcpy(R, cleartext, (ciphertext_length-8));
  memcpy(A, iv, 8);

  for (j=0; j<6; j++) {
    for (i=0; i<n; i++) {
      // I = A | R[1]
      memcpy(I, A, 8);
      memcpy(I+8, R+(i*8), 8);

      // B = AES(K, I)
      encrypt(ctx, 16, B, I);

      // A = MSB(64, B) ^ t where t = (n*j)+i
      A64 = ((uint64_t)B[0] << 56) | ((uint64_t)B[1] << 48) | ((uint64_t)B[2] << 40) | ((uint64_t)B[3] << 32) | ((uint64_t)B[4] << 24) | ((uint64_t)B[5] << 16) | ((uint64_t)B[6] << 8) | (uint64_t)B[7];
      A64 ^= (n*j)+(i+1);
      A[7] = (uint8_t)A64;
      A[6] = (uint8_t)(A64 >> 8);
      A[5] = (uint8_t)(A64 >> 16);
      A[4] = (uint8_t)(A64 >> 24);
      A[3] = (uint8_t)(A64 >> 32);
      A[2] = (uint8_t)(A64 >> 40);
      A[1] = (uint8_t)(A64 >> 48);
      A[0] = (uint8_t)(A64 >> 56);

      //  R[i] = LSB(64, B)
      memcpy(R+(i*8), B+8, 8);

    }
  }

  memcpy(ciphertext, A, 8);
  memcpy(ciphertext+8, R, (ciphertext_length-8));
  o_free(R);
}
nist_keywrap16(const void *ctx, nettle_cipher_func *encrypt,
               const uint8_t *iv, size_t ciphertext_length,
               uint8_t *ciphertext, const uint8_t *cleartext) {
  uint8_t * R = NULL, A[8] = {0}, I[16] = {0}, B[16] = {0};
  uint64_t A64;
  size_t i, j, n;

  if ((R = o_malloc(ciphertext_length-8)) == NULL)
    return;

  n = (ciphertext_length-8)/8;
  memcpy(R, cleartext, (ciphertext_length-8));
  memcpy(A, iv, 8);

  for (j=0; j<6; j++) {
    for (i=0; i<n; i++) {
       
      memcpy(I, A, 8);
      memcpy(I+8, R+(i*8), 8);

       
      encrypt(ctx, 16, B, I);

       
      A64 = ((uint64_t)B[0] << 56) | ((uint64_t)B[1] << 48) | ((uint64_t)B[2] << 40) | ((uint64_t)B[3] << 32) | ((uint64_t)B[4] << 24) | ((uint64_t)B[5] << 16) | ((uint64_t)B[6] << 8) | (uint64_t)B[7];
      A64 ^= (n*j)+(i+1);
      A[7] = (uint8_t)A64;
      A[6] = (uint8_t)(A64 >> 8);
      A[5] = (uint8_t)(A64 >> 16);
      A[4] = (uint8_t)(A64 >> 24);
      A[3] = (uint8_t)(A64 >> 32);
      A[2] = (uint8_t)(A64 >> 40);
      A[1] = (uint8_t)(A64 >> 48);
      A[0] = (uint8_t)(A64 >> 56);

       
      memcpy(R+(i*8), B+8, 8);

    }
  }

  memcpy(ciphertext, A, 8);
  memcpy(ciphertext+8, R, (ciphertext_length-8));
  o_free(R);
}