Bitcoin Forum
March 29, 2024, 08:04:18 AM *
News: Latest Bitcoin Core release: 26.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 »  All
  Print  
Author Topic: [NOW AVAILABLE] BTChip / Ledger HW1 : Bitcoin Hardware Wallet in a USB smartcard  (Read 62441 times)
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 06, 2013, 10:36:09 AM
Last edit: December 05, 2014, 06:37:03 PM by btchip
 #1

Revamped first post  Grin old first post content stays after the line below, for historical purposes only as the scope and supported features changed quite a lot - you don't need to read below the line if you're new to the project

BTChip is a bitcoin/altcoin hardware wallet in a USB smartcard - low cost, secure, and available now - buy from https://buy.hardwarewallet.com (limited promotional offer, 2 cards for 20 €, payable in bitcoins)

See installation and setup instructions on http://www.hardwarewallet.com - BTChip works out of the box with GreenAddress (Chrome application & Android wallet) and Electrum (upcoming release)

For developers :


Updates are always posted on twitter : https://twitter.com/btchip

User tutorials :


User reviews :


-------------------------------------------------------------------------------------------------------------------------------------------------------------------


(Word of warning for people who got a sample at 29c3 and plan to attack it - there will be some chip spoilers during this post)

Hi

Hardware bitcoin related projects look quite alive & kicking in 2012, which is great  Grin here is my take on the topic of smartcard wallets, with a real world implementation

Smartcard wallet vs hardware wallet

First an hopefully unbiaised comparison between smartcard wallets and hardware wallets :

Pro smartcard wallet

  • Hardware security : making sure an attacker who got the device will have a very hard time extracting something useful from it. Also protection against side channel attacks, especially during known-to-leak cryptographic operations.
  • Cost : not considering an additional reader, an initial target cost per unit between 0.5 and 1 BTC is realistic (not considering large volumes). Shipping costs will be lower too, as sending an hardware wallet in a simple letter envelope seems harder.
  • Durability : limited failure options with a single hardware component.

Against smartcard wallet

  • Not Open Source : smartcard chips and associated toolchains are heavily covered by NDAs, which makes sharing the source a pain. It's of course possible to release an Open Source smartcard wallet application running on an open smartcard platform, but you still need to trust the platform.
  • Limited protection against custom malware attacking bitcoin transactions : a hardware wallet will offer a display or buttons to review transactions. It is still possible to offer some protection against this in a smartcard as we will see, but not as extensively.
  • Limited code options : modern smartcards f.e. SC000 based look more and more like typical microcontrollers, if you don't consider the RAM size - however that's still not what you get in a typical secure product. Moreover coding on an "open" platform such as Java Card limits you to what the cryptographic API can offer, which can be an issue for the bitcoin protocol (f.e. ECDSA signature is only offered over SHA-1 for one of the most recent Java Card version, considering the card supports ECDSA first)

BTChip project

 
http://www.btchip.com

1.4.4 firmware specification

This project started as a more or less 2 weeks hack of a generic smartcard OS to offer bitcoin friendly APIs. The initial motivation was to see if it could be done, and also the pleasure of tweaking a project initially dedicated to banking applications to support something outside the system Grin

The chip used is an ST23YT66 which is your regular smartcard microcontroller with a twist : USB support. Which means it can be directly connected into a USB port with no reader necessary.

It features an implementation of the basic smartcard wallet described below an advanced smartcard wallet described in the specification, using USB HID as transport protocol - because it's more convenient than CCID for a general public application.

Here's the roadmap for the coming weeks, which will be updated as things get done :

  • Release the first samples at 29c3 - done
  • Improve the key generation & signing speed. Target is less than 2s, maybe less than 1s Now 900 ms to generate the keypair / 900 ms to sign
  • Maybe support the advanced wallet model (discussion below check the specification), but that's unlikely.
  • Support additional rich clients - so far there's a prototype for bitcoinj and integration into the official client is in progress. If you're a client developer and want a sample to play with, don't be shy and drop me a PM Grin
  • Support web clients - even if Java security has been a bit controversial in the past months (and Java browser support turned into a sick joke on OS X) I've had good success with javahidapi running in an applet container and Java should still be available on public computers, so it can be a starting point. since I wrote this Java security got even worse (hats off to Oracle, that's quite an achievement), so browser plug-ins here we come Cheesy Exposing hidapi through FireBreath is quite easy, so that's the preferred approach so far.

A few words about GlobalPlatform

The GlobalPlatform Card Specifications are a set of specifications implemented by most recent multi application smartcards - they define how the card applications and cryptographic materials are isolated, as well as how to establish a secure transport channel (Secure Channel - think TLS with authentication and optional confidentiality using only symmetric keys) between the card and an external entity.

The smartcard wallet implementations will rely on GlobalPlatform concepts to :

  • Define how keys are inserted into the card
  • Authenticate the user to validate access rights to access specific keys
  • Optionally authenticate the card responses

Smartcard wallet architecture

We assume the user store a lot of keys, not necessarily related to each other (i.e. not necessarily generated by a deterministic wallet)

To support this model, no ECDSA key will be stored on the smartcard and the smartcard will only manipulate the private component of an ECDSA key (S, 32 bytes) in an encrypted form.

A key used to encrypt private component of an ECDSA key is called a Context Key. Context Keys are stored on the smartcard itself and never revealed. The suggested encryption algorithm is Triple DES in CBC mode (because Triple DES capable cryptoprocessors are still way more common than AES capable cryptoprocessors nowadays on smartcard chips).

A bitcoin client stores the private key in an encrypted form along with the reference of the Context Key used to access it. It then sends SHA-256 hashes to sign to the smartcard for a non transaction aware smartcard wallet, or each component of the transaction to sign for a transaction aware smartcard wallet, along with the encrypted private key to sign with.

A Context Key can be associated to a specific GlobalPlatform Secure Channel. In this case, the user should be authenticated to the Secure Channel before being able to sign a transaction.

Basic smartcard wallet (non transaction aware)

The basic smartcard wallet just knows how to generate a keypair over the bitcoin ECDSA curve, and sign something. It is not aware of anything else bitcoin specific, and does not need to support SHA-256 either.

The following APIs are defined :

Generate Keypair : takes a Context Key reference, generates a keypair over secp256k1, returns the public component of the key (W) and the encrypted private component of the key (S') using the Context Key.

Import Private Key : takes a Context Key reference and a cleartext private key component (S), returns the encrypted private component of the key (S') using the Context Key.

Sign : takes an encrypted private key component (S'), the SHA-256 hash to sign, and returns the ASN-1 encoded signature components.

Verify (optional) : takes a public key component (W), the SHA-256 hash to verify, the signature and returns ok or not ok.

Advanced smartcard wallet (transaction aware) (old version, check the posts below for the updated version)

The following description is mostly outdated and kept only for reference - check the firmware specification instead

The advanced smartcard wallet proposal uses a simple concept to defeat useful malware : all output addresses must be authenticated by the card when included in a transaction.

In this model, before starting a transaction you'd take the output addresses, provide them to the card to be encrypted on a trusted computer or a different platform, then go on with the transaction signing.

Two new type of keys are defined, the Address Key, which is used to encrypt an address, and the Secure Hash key, which is used to encrypt a SHA-256 context.

In this implementation the smartcard needs to support SHA-256 and optionally RIPEMD-160 if automated keys generation for change is desired

The following APIs are defined :

Generate Keypair For Change : takes a Context Key reference, an Address Key reference, generates a keypair over secp256k1, returns the public component of the key (W), the encrypted private component of the key (S') using the Context Key, and the associated encrypt address.

Encode Address : takes an output address, an Address Key reference and returns an encrypted address that the smartcard will authenticate later.

Secure Hash Generic : takes a generic part of the transaction which is not an Output script, a Secure Hash context (or nothing if creating a new hash), a Secure Hash key reference and returns an updated (or new) Secure Hash context. The Secure Hash context holds the context of the SHA-256 hash, encrypted by the smartcard. It is sent back to the host instead of being kept in RAM in case people are interested to have a distributed implementation. This function must validate the provided data i.e. make sure that no Output script can be hashed by this function (f.e. by fragmenting it into meaningless parts).

Secure Hash Output Script : takes an Output script, a Secure Hash context, a Secure Hash key reference, a list of encrypted addresses and associated Address Key references and returns an updated Secure Hash context. The Output script structure is parsed and only accepted if the given address matches one of the encrypted addresses passed.

Sign Secure Hash : takes an encrypted private key component (S'), a Secure Hash context, a Secure Hash key reference and returns the ASN-1 encoded signature components.

Protecting against custom malware

Creating multiple Context Keys can be effective protected by a Secure Channel can help fragmenting the risks for large wallets - supposing an all powerful malware grabbed the authentication key of the Secure Channel and can play transactions, the risks are limited to the private keys linked to this Context Key.

Another simple method to protect against custom malware using an USB implementation can be to rely on an annoying fact : powering off a USB device by software is painful. Using this model, we can choose to accept one signature per session and force the user to unplug/plug again the device for each signed output - a cheap way to check that no additional outputs were added, but requires free fingers to count and doesn't prevent a malware that'd just replace a legitimate transaction by a fake one rather than adding outputs to a legitimate one.

Feel free to comment and improve on this  Grin

1711699458
Hero Member
*
Offline Offline

Posts: 1711699458

View Profile Personal Message (Offline)

Ignore
1711699458
Reply with quote  #2

1711699458
Report to moderator
1711699458
Hero Member
*
Offline Offline

Posts: 1711699458

View Profile Personal Message (Offline)

Ignore
1711699458
Reply with quote  #2

1711699458
Report to moderator
1711699458
Hero Member
*
Offline Offline

Posts: 1711699458

View Profile Personal Message (Offline)

Ignore
1711699458
Reply with quote  #2

1711699458
Report to moderator
"Bitcoin: the cutting edge of begging technology." -- Giraffe.BTC
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1711699458
Hero Member
*
Offline Offline

Posts: 1711699458

View Profile Personal Message (Offline)

Ignore
1711699458
Reply with quote  #2

1711699458
Report to moderator
1711699458
Hero Member
*
Offline Offline

Posts: 1711699458

View Profile Personal Message (Offline)

Ignore
1711699458
Reply with quote  #2

1711699458
Report to moderator
finway
Hero Member
*****
Offline Offline

Activity: 714
Merit: 500


View Profile
January 06, 2013, 01:34:35 PM
 #2

Cool

paraipan
In memoriam
Legendary
*
Offline Offline

Activity: 924
Merit: 1004


Firstbits: 1pirata


View Profile WWW
January 06, 2013, 02:19:32 PM
 #3

Kick ass! Read half of your post and had to comment  Smiley

(goes back reading...)

BTCitcoin: An Idea Worth Saving - Q&A with bitcoins on rugatu.com - Check my rep
Mike Hearn
Legendary
*
Offline Offline

Activity: 1526
Merit: 1128


View Profile
January 06, 2013, 06:17:46 PM
 #4

I saw your clone of bitcoinj, great to see this announced. It sounds very cool.

I have some questions.

Firstly, you state that this chip can be attached directly to a USB port without any reader necessary, but the image you provide looks like a regular smartcard, which won't physically fit. So how does this work, exactly? Could you post a photo of one attached to your computer?

Secondly, I'm still a little confused as to use cases. As you admit, because it simply signs hashes in the standard mode, this is security-wise equivalent to having an encrypted wallet on a PC. If malware gets onto the machine it has to wait until the user makes a transaction, and can then steal all the funds. So a BTChip seems to have same security as a strong password, with the downside that you cannot back it up and you have to carry it around. Could you elaborate more on where you see this product fitting in? For instance, could it store time horizons (block time of earliest transaction, latest transaction) and be used as a kind of card-based wallet?

btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 06, 2013, 08:10:25 PM
 #5

I saw your clone of bitcoinj, great to see this announced. It sounds very cool.

I have some questions.

Firstly, you state that this chip can be attached directly to a USB port without any reader necessary, but the image you provide looks like a regular smartcard, which won't physically fit. So how does this work, exactly? Could you post a photo of one attached to your computer?

Hi, sure. First you cut the shape in the center



Then you fold it



Then you can insert it



Quote
Secondly, I'm still a little confused as to use cases. As you admit, because it simply signs hashes in the standard mode, this is security-wise equivalent to having an encrypted wallet on a PC. If malware gets onto the machine it has to wait until the user makes a transaction, and can then steal all the funds.

The basic use case is indeed very similar to an encrypted wallet, but offers some additional security in my opinion.

One thing is that once a malware obtains the passphrase to an encrypted wallet, it can grab the private keys and use them later without requiring any interaction from the user. Using a smartcard wallet, the malware can request the smartcard to sign something using those keys, as long as the smartcard is connected and agrees to sign (you could set a session based limit according to the number of outputs you plan to sign, for example, and after this the card would have been to be removed / inserted again to be operational, or other creative countermeasures).

The biggest difference is that the private key is never manipulated in a usable form by the host.

You could also make the malware attack less successful by using different encryption keys for the private keys, each one using a different PIN.

Quote
So a BTChip seems to have same security as a strong password, with the downside that you cannot back it up and you have to carry it around.

You can back it up, and it's very important to do so Grin the idea is to generate the context keys (encrypting the private keys) on a trusted computer when you first use the card (or decide to create a new context key), and keep the Triple DES key value in a safe place (printed / gpg encrypted ...). Thus you can exchange keys between another client implementation and the smartcard if you wish.

Quote
Could you elaborate more on where you see this product fitting in?

I can see it fitting some space between the pure software approach and the hardware wallet for people wanting some additional security, as it's cheaper to produce and distribute. And rebrand, if you consider the BTChip form factor (f.e. a web based wallet providing this to its users). Also as a side note more secure if physically attacked.

Now if the consensus is that basic mode is not secure enough, then I'll see how this can be improved and we can discuss it.

Quote
For instance, could it store time horizons (block time of earliest transaction, latest transaction) and be used as a kind of card-based wallet?

yes it could do that, although it has a very limited storage capacity (on this version, 16 kb). Can you elaborate more on this ?

paybitcoin
Member
**
Offline Offline

Activity: 85
Merit: 10


1h79nc


View Profile WWW
January 06, 2013, 08:37:38 PM
 #6

Secondly, I'm still a little confused as to use cases. As you admit, because it simply signs hashes in the standard mode, this is security-wise equivalent to having an encrypted wallet on a PC. If malware gets onto the machine it has to wait until the user makes a transaction, and can then steal all the funds. So a BTChip seems to have same security as a strong password, with the downside that you cannot back it up and you have to carry it around. Could you elaborate more on where you see this product fitting in? For instance, could it store time horizons (block time of earliest transaction, latest transaction) and be used as a kind of card-based wallet?
I can see it adding a bit more trust in a centralized, cloud-based card-provider scenario. The customer wins because the card provider doesn't have any way of getting at the funds directly as only the encrypted private key is stored (short of breaking 3DES.) They can also backup the funds directly in case the card provider goes defunct.

If you add more verification in the card itself to only allow signed transactions from the card provider, then the card provider and customer are secure in the fact that the signed transactions are not affected by malware (except if the recipient/merchant generating the transaction is infected, but at least someone can see it before it is signed.)

The customer would still have to trust the card provider not to spend all the funds as part of the next transaction, but then the card provider would also have to be cooperating with the merchant terminal/ host software provider to hide this fact when showing the receipt before signing.

Another note on this smartcard, there will always be some sort of cloud provider/host in the mix as the actual private key is _not_ stored in the card itself. Therefore (and as btchip just posted) it needs to be transferred to the card for signing.

btchip, if there is 16 kb of storage space available, is there a way to store and transfer out the encrypted key directly? Then you could do offline signing, as long as you trust the host software. Also, is it kilobits (Kb) or kilobytes (KB)? I see in the chip posted there is 66 Kbytes of User EEPROM...
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 06, 2013, 08:48:11 PM
 #7

btchip, if there is 16 kb of storage space available, is there a way to store and transfer out the encrypted key directly? Then you could do offline signing, as long as you trust the host software. Also, is it kilobits (Kb) or kilobytes (KB)? I see in the chip posted there is 66 Kbytes of User EEPROM...

16 kilobytes. There are 66 Kbytes indeed, which are mostly used by the bitcoin patch in this implementation Grin

so yeah, you'd be able to store a few private keys, too. It's just less convenient when the card is lost, and less interoperable with other clients.

another idea for a (stupid) countermeasure against malware : generate a one time pad, and when signing, ask the user for a random value.

Mike Hearn
Legendary
*
Offline Offline

Activity: 1526
Merit: 1128


View Profile
January 06, 2013, 09:17:24 PM
 #8

By time horizons, I mean, if I buy a card and put some keys in it and then load up those keys with some coins, if I give it to somebody else I want them to be able to quickly load up a usable wallet. For sites that have a full index of the blockchain (like blockchain.info or things that use their API) you don't need any other data, but most nodes don't have such an index. For them knowing the block span which may be useful to scan can speed up synchronization immensely. It means storing two extra ints, so hardly a big deal if you have 16kb.
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 06, 2013, 09:27:05 PM
 #9

ok I see, just for synchronization purposes. Yes, no problem doing that, creating extra files is already supported in the current version (and security restrictions can apply for read / update / delete access). I just need to map it in the client API.

btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 10, 2013, 01:28:19 AM
 #10

Some news ...

On the key generation/signing speed, things are definitely improving.

More interestingly, we found a way to reclaim more free space on the chip. Which means the advanced scenario is definitely possible, and I'd like to improve it a bit.

The target is to have something that is easy to use and difficult to impersonate, of course, and define a protocol that could be applied to any hardware device without a display and buttons. The previous advanced protocol is a bit too complicated to use if all new addresses have to be encoded, IMHO.

So, a new idea, authenticating only the addresses :

When the device is received, a table is generated and can be printed. The table is a 0...255 index with values associated to user actions to perform. Values are assigned randomly to the indexes

  • From 1 to 34 : enter char 1 to 34 of the address
  • From 100 to 157 : enter number of time the character 0..57 of base58 is present in the address

When requesting a signature to an address, the dongle will generate a few challenges (number can be fixed by the owner) - each challenge is a 0...255 random number, and the user has to perform the action matching this index to proceed

The client software can display all information needed for computation, and the user can recheck its validity easily.

btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 21, 2013, 10:51:57 PM
 #11

Some news ...

Key pair generation and signature are both at 900 ms each now.

Rather than adding a new giant wall of text to this forum Grin the specification for the upcoming new firmware release has been published on github :

btchip 1.4.1 firmware specification (do not use the table of contents on this link, clone it locally if you want to do that)

Description of the challenge mechanism used to authenticate addresses - I've tried my best to be confusing for an automated malware, and hopefully not too confusing for the user, but let me know  Wink

Now development of the firmware goes on and the first integration of the new features (including some absolutely non nice UI to play the challenge game) will be done for bitcoinj.

btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 27, 2013, 08:28:50 AM
 #12

Another thread reminded me of a use case for this smartcard wallet which might not be obvious to everybody - server side security.

When you read the specification you might wonder why during the hashing process the hash-in-progress is sent encrypted to the host rather than staying on the chip - this is done to support transparent load balancing with several chips.

You can then support X * chips transactions per second on a server with a very good security level for cheap - an attacker will need to keep connected to the server in order to do something useful.



Of course if you plan to compete with Visa and Mastercard, old fashioned Hardware Security Modules are still recommended, but don't come with the same price tag  Grin




2112
Legendary
*
Offline Offline

Activity: 2128
Merit: 1060



View Profile
January 27, 2013, 05:20:24 PM
 #13

  • Not Open Source : smartcard chips and associated toolchains are heavily covered by NDAs, which makes sharing the source a pain. It's of course possible to release an Open Source smartcard wallet application running on an open smartcard platform, but you still need to trust the platform.
OK, lets assume that I have no reservations against signing NDAs and developing wholy closed source. Could you please answer the following questions:

1) What is the cost of one complete development seat for the target platform?
2) Would the toolchain vendor even be willing to consider NDA from an one or two person shop (and no personal assets pledged) as valid?

Please comment, critique, criticize or ridicule BIP 2112: https://bitcointalk.org/index.php?topic=54382.0
Long-term mining prognosis: https://bitcointalk.org/index.php?topic=91101.0
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
January 27, 2013, 06:19:57 PM
 #14

ok, I assume you've already explored the "open" alternatives such as Java Card which are easier to design for and want to go native for your projects.

Then 1) is probably not the issue. I'd say less than 10k$ whatever the vendor. Often less than 5k$.

2) is more tricky. It's fine for a small shop if you can show references (preferred use case, but it might be a chicken and egg issue for you) or are extremely convincing, and in all cases can justify a business plan of a large amount (I'd say 1 million should be fine) of sold units for the next few years, most likely including a large pre-paid order.
 
I'd recommend attending a specialized industry show such as Cartes where you can find all vendors and see who's the most interested in your project.

2112
Legendary
*
Offline Offline

Activity: 2128
Merit: 1060



View Profile
January 27, 2013, 06:37:56 PM
 #15

ok, I assume you've already explored the "open" alternatives such as Java Card which are easier to design for and want to go native for your projects.

Then 1) is probably not the issue. I'd say less than 10k$ whatever the vendor. Often less than 5k$.

2) is more tricky. It's fine for a small shop if you can show references (preferred use case, but it might be a chicken and egg issue for you) or are extremely convincing, and in all cases can justify a business plan of a large amount (I'd say 1 million should be fine) of sold units for the next few years, most likely including a large pre-paid order.
 
I'd recommend attending a specialized industry show such as Cartes where you can find all vendors and see who's the most interested in your project.

Thank you very much. I was mostly courious if the situation had changed since the last time I researched it. Only costs went somewhat down, other than that things haven't changed much.

Please comment, critique, criticize or ridicule BIP 2112: https://bitcointalk.org/index.php?topic=54382.0
Long-term mining prognosis: https://bitcointalk.org/index.php?topic=91101.0
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
February 25, 2013, 11:41:02 PM
 #16

In case some bitcoiners are attending Mobile World Congress 2013, I'll have a few samples available on the 26th and 27th with an intermediate firmware version (faster than the one distributed at 29c3, but without the anti malware features) - just leave a message.

Then development of the new firmware will resume faster, hopefully Grin



btcusr
Sr. Member
****
Offline Offline

Activity: 405
Merit: 255


@_vjy


View Profile
March 15, 2013, 10:30:01 AM
 #17

Is it possible to use two different keys in such a way that either of those keys could sign?
Just for the single key failover case / redundancy.
Hope it would act like duplicate door keys..

btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
March 15, 2013, 06:54:57 PM
 #18

Is it possible to use two different keys in such a way that either of those keys could sign?
Just for the single key failover case / redundancy.
Hope it would act like duplicate door keys..


yes, as long as two chips share the same context (triple DES) keys, they can be exchanged.

yokosan
Hero Member
*****
Offline Offline

Activity: 700
Merit: 500


View Profile
March 15, 2013, 08:00:04 PM
 #19

Contact Kim Dotcom. He has a job for you.
btchip (OP)
Hero Member
*****
Offline Offline

Activity: 623
Merit: 500

CTO, Ledger


View Profile WWW
March 16, 2013, 05:32:12 AM
 #20

Contact Kim Dotcom. He has a job for you.

don't worry, we thought about that Smiley

(this space reserved for a not really useful but fun device picture)

Pages: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!