BAB 5 ATOMIK DAN TRANSAKSI

Smart card muncul sebagai perangkat yang dipilih untuk aplikasi penyimpan data rahasia pribadi dan penyedia layanan otentikasi pada lingkungan mobile dan distributed. Akan tetapi, dengan smart card, ada resiko kegagalan waktu eksekusi applet. Kegagalan dapat terjadi karena kesalahan komputasi, user smart card tiba-tiba mengeluarkan kartu dari CAD, memutus daya ke CPU kartu, dan mengakhiri eksekusi beberapa applet. Pengeluaran kartu dari CAD tersebut disebut tearing atau card tear. Resiko dari eksekusi yang belum selesai mengharuskan untuk menjaga integrasi operasi pada data yang penting dalam smart card.

JCRE menyediakan mekanisme yang handal untuk menjamin operasi yang atomik. Mekanisme ini mempunyai 2 level. Pertama, platform Java Card menjamin bahwa beberapa update ke sebuah field dalam sebuah objek persisten atau sebuah field kelas bersifat atomik. Kedua, platform Java Card mendukung model transaksi, sehingga sebuah applet dapat mengelompokkan sekumpulan update yang dilakukannya ke dalam sebuah transaksi. Dalam model ini, keatomikan semua update dijamin.

Pembahasan kali ini menjelaskan apa yang dimaksud atomik dalam platform Java Card dan bagaimana developer applet dapat memprogram sebuah applet yang menggunakan transaksi untuk menjaga integritas data.

ATOMIK

Pada platform Java Card, atomik berarti bahwa beberapa update ke sebuah field objek persisten (meliputi sebuah elemen array) atau sebuah field kelas dijamin selesai atau dikembalikan ke nilai aslinya jika error terjadi selama update dilakukan. Contohnya, sebuah field pada sebuah objek berisi nilai 1, dan sedang di-update agar bernilai 2. Kartu tiba-tiba dikeluarkan dari CAD saat kartu menulisi field. Saat daya dikembalikan, field tidak diisi dengan nilai random tapi dikembalikan ke nilai sebelumnya yaitu 1.

Konsep atomik berlaku pada konsep penyimpanan yang persisten. Konsep atomik menjelaskan bagaimana JCRE menangani elemen data saat kehilangan daya atau saat kesalahan lain selama update dilakukan pada elemen tersebut. Fitur atomik JCRE tidak berlaku pada array transien. Update elemen pada array transien tidak menjaga nilai elemen sebelumnya saat terjadi kehilangan daya. Setelah kartu dimasukkan ke dalam CAD lagi, elemen pada array transien diubah ke nilai default-nya (nol, false, atau null).

UPDATE DATA BLOK DALAM ARRAY

Kelas javacard.framework.Util menyediakan metode arrayCopy yang menjamin sifat atomik pada peng-update-an blok pada elemen-elemen data dalam sebuah array:

public static short arrayCopy (byte[] src, short srcOff, byte[] dest, short desOff, short length);

Metode Util.arrayCopy menjamin semua byte berhasil dikopi atau array tujuan dikembalikan ke nilai byte sebelumnya. Jika array tujuan adalah transien, fitur atomik tidak ditangani.

Namun, arrayCopy membutuhkan banyak operasi menulis ke EEPROM untuk mendukung atomik sehingga membuatnya menjadi lambat. Applet bisa jadi tidak memerlukan atomik untuk peng-update-an array. Metode Util.arrayCopyNonAtomic disediakan untuk tujuan ini:

public static short arrayCopyNonAtomic (byte[] src, short srcOff, byte[] dest, short desOff, short length);

Metode arrayCopyNonAtomic tidak menggunakan fasilitas transaksi saat operasi kopi bahkan jika transaksi sedang berlangsung. Sehingga metode ini hanya digunakan jika isi array tujuan dapat ditinggalkan dalam keadaan setengah termodifikasi saat kejadian kehilangan daya di pertengahan operasi kopi. Metode yang sama Util.arrayFillNonAtomic, dengan tidak atomik mengisi elemen dari array byte dengan nilai tertentu:

public static short arrayFillNonAtomic (byte[] bArray, short bOff, short bLen, byte bValue);

TRANSAKSI

Sifat atomik menjamin modifikasi pada sebuah elemen data. Namun, applet mungkin perlu update secara atomik beberapa field berbeda pada beberapa objek berbeda. Contohnya, transaksi kredit dan debit mungkin perlu sebuah applet purse untuk menaikkan nomer transaksi, mengubah balance, dan menulis sebuah log transaksi, semuanya sebagai sebuah unit kerja yang atomik.

Pembaca mungkin lebih familiar dengan transaksi database (“begin”, “commit”, dan “rollback”) untuk menjamin update ke beberapa nilai, berhasil seluruhnya atau tidak seluruhnya. Teknologi Java Card mendukung model transaksi yang sama dengan “commit” dan “rollback” untuk menjamin operasi yang kompleks dapat dilakukan secara atomik (apakah operasi tersebut akan selesai sluruhnya atau hasil yang baru sebagian tidak berlaku). Mekanisme transaksi melindungi terhadap kejadian seperti kehilangan daya di pertengahan transaksi dan terhadap kesalahan program yang mungkin menyebabkan gangguan terhadap data yang menjadikan semua langkah transaksi tidak selesai dengan normal.

Transaksi “commit”

Sebuah transaksi dimulai oleh pemanggilan metode JCSystem.beginTransaction dan diakhiri dengan pemanggilan metode JCSystem.commitTransaction:

//memulai sebuah transaksi

JCSystem.beginTransaction();

//semua modifikasi dalam sekumpulan update data persisten bersifat sementara
//sampai transaksi “commit”


//transaksi “commit

JCSystem.commitTransaction();

Perubahan dalam sebuah transaksi adalah kondisional – field atau elemen array kelihatan diubah. Membaca field atau elemen array kembali menghasilkan nilai kondisional terakhirnya, tapi update tidak di-commit sampai metode JCSystem.commitTransaction dipanggil.

Transaksi “abort”

Transaksi dapat digagalkan baik oleh applet atau JCRE. Jika applet mengalami masalah internal, maka transaksi dapat cepat dibatalkan dengan memanggil metode JCSystem.abortTransaction. Menggagalkan sebuah transaksi menyebabkan JCRE menggagalkan perubahan yang dilakukan saat transaksi dan mengembalikan field atau elemen array yang diubah ke nilai sebelumnya. Transaksi harus sedang berlangsung saat metode abortTransaction dipanggil, jika tidak, JCRE membuang TransactionException.

Saat JCRE mendapatkan kembali kendali pada applet dengan transaksi yang masih berlangsung – saat applet tidak commit secara eksplisit atau tidak abort – JCRE secara otomatis memanggil metode abortTransaction. Sama halnya, JCRE abort transaksi jika sebuah eksepsi dibuang pada transaksi dan eksepsi tidak ditangani oleh applet.

Jika daya dihilangkan atau error terjadi saat transaksi, JCRE memanggil fasilitas “rollback” pada internal JCRE setelah kartu diberi daya untuk mengembalikan data ke nilai sebelum transaksi.

Pada beberapa kasus, objek transien dan persisten yang dibuat saat sebuah transaksi gagal (karena kehilangan daya, reset kartu, kesalahan komputasi, atau sebuah aksi “abort”) dihapus dan memorinya dibebaskan oleh JCRE.

Transaksi bersarang (nested transaction)

Tidak seperti kebanyakan transaksi database, transaksi dalam platform Java Card tidak bisa bersarang. Hanya ada satu transaksi yang berlangsung pada satu waktu. Syarat ini dikarenakan resource pada smart card yang terbatas.

Jika JCSystem.beginTransaction dipanggil saat sebuah transaksi sedang berlangsung, JCRE membuang TransactionException. Applet dapat mengetahui apakah sebuah transaksi sedang berlangsung atau tidak dengan memanggil metode JCSystem.transactionDepth. Metode ini menghasilkan 1 jika sebuah transaksi sedang berlangsung, 0 jika tidak.

Kapasitas “commit”

Untuk mendukung rollback transaksi yang tidak di-commit, JCRE menyediakan commit buffer dimana isi original dari field yang di-update disimpan sampai transaksi commit. Jika kegagalan terjadi sebelum transaksi selesai, field yang bersangkutan dalam transaksi dikembalikan ke “isi original” (berasal dari commit buffer). Lebih banyak operasi di dalam sebuah blok transaksi, semakin besar commit buffer yang diperlukan untuk menampungnya.

Ukuran commit buffer bervariasi dari satu implementasi ke lainnya, tergantung pada memori yang tersedia pada kartu. Umumnya, commit buffer yang dialokasikan dalam sebuah implementasi JCRE adalah cukup besar untuk menampung kebutuhan banyak applet – sebuah applet biasanya mengakumulasi 10 byte selama transaksi. Namun, karena resource pada smart card yang terbatas, penting bahwa hanya update dalam unit logis dari operasi dimasikkan dalam sebuah transaksi. Meletakkan banyak hal dalam sebuah transaksi adalah tidak mungkin.

Sebelum melakukan transaksi, applet dapat memeriksa ukuran dari commit buffer yang tersedia pada ukuran data yang memerlukan update atomik. Kelas JCSystem menyediakan 2 metode untuk membantu applet memutuskan berapa banyak kapasitas commit tersedia pada implementasi platform Java Card.

  • JCSystem.getMaxCommitCapacity() menghasilkan jumlah byte total dalam commit buffer.
  • JCSystem.getUnusedCommitCapacity() menghasilkan jumlah byte yang tidak digunakan dalam commit buffer.

Disamping untuk menyimpan isi field yang dimodifikasi saat transaksi, commit buffer menangani tambahan byte dari data yang overhead, seperti lokasi-lokasi dari field. Jumlah data yang overhead tergantung pada jumlah field yang sedang dimodifikasi dan pengimplementasian sistem transaksi. Kapasitas commit yang dihasilkan oleh 2 metode adalah jumlah byte total dari data persisten – termasuk overhead – yang dapat dimodifikasi saat transaksi.

Jika kapasitas commit dilewati saat transaksi, JCRE membuang sebuah TransactionException. Bahkan saat transaksi masih berlangsung, kecuali jika di-abort secara eksplisit oleh applet atau oleh JCRE.

TransactionException

JCRE membuang sebuah TransactionException jika jenis masalah tertentu seperti transaksi bersarang atau commit buffer meluap, ditemukan dalam transaksi.

TransactionException adalah bagian dari RuntimeException. TransactionException menyediakan sebuah reason code untuk menunjukkan penyebab eksepsi. Eksepsi dan reason code pada Java Card dijelaskan pada Bab 6. Berikut adalah reason code yang didefinisikan dalam kelas TransactionException:

  • IN_PROGRESS – beginTransaction dipanggil jika transaksi siap berlangsung (in progress).
  • NOT_IN_PROGRESS – commitTransaction atau abortTransaction dipanggil jika transaksi tidak berlangsung lagi (not in progress).
  • BUFFER_FULL – dilakukan update ke memori persisten saat transaksi yang menyebabkan commit buffer meluap.
  • INTERNAL_FAILURE – sebuah masalah internal yang fatal terjadi dalam sistem transaksi.

Jika TransactionException tidak ditangkap oleh applet, maka akan ditangkap oleh JCRE. Pada kasus yang lebih baik, JCRE secara otomatis menggagalkan transaksi.

Variabel local dan objek transien saat transaksi

Pembaca harus sadar bahwa hanya update ke objek persisten yang bisa dilakukan dalam transaksi. Update ke objek transien dan variabel lokal (termasuk parameter pada metode) tidak pernah dibatalkan terlepas apakah mereka ada dalam transaksi atau tidak. Variabel lokal dibuat di stack pada Java Card, yang berada dalam RAM.

Bagian kode berikut mendemonstrasikan 3 operasi kopi yang melibatkan array transien dengan nama “key_buffer”. Saat transaksi abort, operasi kopi array maupun update dari elemen “key_buffer” pada perulangan “for” tidak dijaga oleh transaksi. Sama halnya, lokal variabel dengan nama “a_local” mempertahankan nilainya yaitu 1.

byte[] key_buffer = JCSystem.makeTransientByteArray (KEY_LENGTH, JCSystem.CLEAR_ON_RESET);

JCSystem.beginTransaction();

Util.arrayCopy(src, src_off, key_buffer, 0, KEY_LENGTH);

Util.arrayCopyNonAtomic(src, src_off, key_buffer, 0, KEY_LENGTH);

for(byte i=0; i<KEY_LENGTH; i++)

key_buffer[i] = 0;

byte a_local = 1;

JCSystem.abortTransaction();

Karena variabel lokal atau elemen array transien tidak diikutsertakan dalam transaksi, pembuatan objek dan penempatan objek ke variabel lokal atau ke elemen array transien perlu dipertimbangkan secara hati-hati. Ini contoh kodenya:

JCSystem.beginTransaction();

//ref_1 adalah sebuah field instans (objek)

ref_1 = JCSystem.makeTransientObjectArray(LENGTH, JCSystem.CLEAR_ON_DESELECT);

//ref_2 adalah variabel local

ref_2 = new SomeClass();

//memeriksa status

If (!condition)

JCSystem.abortTransaction();

Else

JCSystem.commitTransaction();

return ref_2;

Pada contoh, instan field ref_1 menyimpan sebuah referensi ke objek transien, dan variabel lokal ref_2 menyimpan sebuah referensi ke objek persisten. Seperti yang dijelaskan sebelumnya, jika transaksi abort, objek persisten dan transien yang dibuat selama transaksi secara otomatis dihapus. Ini tidak mempunyai efek samping pada instan field ref_1, karena isi ref_1 dikembalikan ke nilai originalnya jika transaksi tidak selesai. Namun, masalah besar terjadi setelahnya, saat objek yang dibuat ditempatkan ke variabel lokal. Pada saat transaksi mengalami kegagalan, JCRE menghapus objek; namun, ref_2 masih menunjuk ke lokasi dimana tidak ada objek lagi. Situasi semakin memburuk jika ref_2 digunakan sebagai nilai yang dikembalikan. Dalam hal ini, pemanggil akan menerima sebuah dangling pointer (pointer yang menggantung).

Untuk mencegah munculnya dangling pointer yang membahayakan keamanan, JCRE menjamin referensi ke objek yang dibuat saat transaksi abort harus menjadi null. Solusi ini mungkin tidak ideal, tapi ini mencegah pelanggaran terhadap keamanan dan meminimalkan overhead pada sistem.

Contoh ini tidak berlaku untuk kebanyakan applet, karena membuat objek dalam metode sangat dilarang. Jika memungkinkan, applet harus menyediakan semua objek yang dibutuhkannya selama inisialisasi applet (lihat bab 7). Namun, implementor instaler Java Card mungkin perlu berurusan dengan pembuatan objek yang cukup besar dalam transaksi dan harus menghindari skenario yang dijelaskan dalam kode.

Sumber: from book Java card Technology for Smart Card, Architecture and Programmer’s Guide

This entry was posted in Java Card. Bookmark the permalink.