Yubikey NEO

Two Factor authentication and general improvement of my security infrastructure was long on my todo list. Some month ago I finally purchased a Yubikey NEO from Yubico and try to consistently use it as second factor, as well as gpg signing/encrypting device.

yubikey-neo

I am trying to get the best out of my Yubikey NEO by using as many of its functionality, in particular: Smartcard for my GNuPG keys, OTP similar to Google Authenticator and similar, as well as challenge-response for additional login security, as well as all that over NFC to not keep keys/passwords on my mobile phone.

While there are loads of guides (see the previous article on GnuPG for some of them), many of them are out-of-date for current distributions and GnuPG etc. So I tried to collect all I could find – not the least to have a place to look it up in case I forget it again.

The Hardware

The Yubikey NEO is a great peace of hardware. I not even remotely understand how they manage that this little beast can do all these things and still work out without mixing things up. As far as I understand (please correct me) it has three independent circuits of communication:

  • HID mode – working as keyboard and sending keystrokes
  • CCID mode (smartcard) – for PIV / GnuPG / OpenGPG functionality
  • NFC – for communication with your mobile

On top of these circuit of communication there is a variety of applications to make the most out of your Yubikey:

  • various OTP: Yubico OTP (against a special server), TOTP, OATH-HOTP, Static PW, Challenge-Response
  • Fido U2F mode – universal two-factor authentication mode
  • OpenGPG smartcard support – 4 slots for private keys
  • PIV

Yubikey mode setup

There are several modes, and using the ykpersonalize tool (readily available for Windows, Mac, Linux, and in the Debian package yubikey-personalization) one can program the key to work in a variety of modes. I chose to activate all options by passing in -m86 which stand for OTP/U2F/CCID composite device with MODE_FLAG_EJECT.

$ ykpersonalize -m86
Firmware version 3.4.3 Touch level 1792 Unconfigured
 
The USB mode will be set to: 0x86
 
Commit? (y/n) [n]: y
$

It is a good idea to unplug and replug the key after this operation.

Yubikey udev rules for user access

To allow users but root to use the Yubikey, additional udev rules are necessary:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0116", TAG+="uaccess"

which I put into /etc/udev/rules.d/99-yubikeys.rules on Debian. After that another unplug and replug should allow normal user to access the key. This can be checked by calling getfacl on the newly created /dev/hidraw? device.

Using the HID/Challenge-Response mode (slot 2)

If you want to secure your login with an additional second factor, there are several options documented on the Yubico site concerning yubico-pam. Since I cannot be sure to be always online with my laptop, I choose Challenge-Response authentication, and followed one-to-one Yubico’s docs Local Authentication Using Challenge Response. Basically it boils down to install libpam-yubico, select mode-challenge-response when asked for configuration. Then one needs to personalizing the key (in particular slot 2) for challenge response with:

$ ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
...
Commit? (y/n) [n]: y
$

Next we need to save the challenge and expected response to the user’s directory:

$ mkdir $HOME/.yubico
$ ykpamcfg -2 -v
...
Stored initial challenge and expected response in '/home/norbert/.yubico/challenge-123456'.
$

It might be a good idea to try this out, and if it works, activate it also for root. But be careful – no key no login 😉

Challenge: I am currently searching for a method to replace the second factor of they key optionally with a different authentication method, like a very difficult passphrase. This way I could log in even without my key, but in this case would need the complicated passphrase. From my reading of the pam manuals it seems to be possible, and I am planning to use pam_ssh and a specific login key with a complicated passphrase. I will report back when this is done.

YubiOATH (TOTP) – Time based One Time Passwords (aka Google Authenticator style)

Without any setup whatsoever this worked out of the box. I use the Yubico Authenticator on my Android phone, and the dedicated application for the Linux desktop to create second factors for all kind of applications. Currently I am using it with Google login, Github, DropbBox, and WordPress (via the Two Factor plugin which can also be tweaked to use the NEO key as USB key via the FIDO U2F).

Challenge: If I start the Yubico Personalization GUI, I see two free slots – so where are the TOTPs computed? That also means that I have one slot free – and for now I don’t know what to do with it 😉

Yubikey OpenGPG applet setup

The Yubikeys support OpenPGP, and the applet is pre-installed (afaik), meaning you can directly configure the key and upload your keys. Here I use gpg2 (2.1) as it seems to better support card operations. To not interfere with the current gpg setup I use a temporary gpg home:

$ mkdir gpgtmp
$ chmod go-rwx gpgtmp
$ gpg2 --homedir gpgtmp --list-keys
gpg: keybox 'gpgtmp/pubring.kbx' created
gpg: gpgtmp/trustdb.gpg: trustdb created

Warning: The YubiKey NEO only supports 2048bit keys. If you want 4096bit keys you need to use one of the newer YubiKey 4, which gives you this option, but does not have support for NFC, and thus no way to interact with an Android (or other) mobile phone.

Check the correct version of the applet

There has been a bug in an older version of the applet, but since 2 years all keys sold should have a correct applet. You can check by:

$ gpg-connect-agent --homedir gpgtmp --hex "scd apdu 00 f1 00 00" /bye"
gpg-connect-agent: no running gpg-agent - starting '/usr/bin/gpg-agent'
gpg-connect-agent: waiting for the agent to come up ... (5s)
gpg-connect-agent: connection to agent established
D[0000]  01 00 10 90 00                                     .....           
OK

Looking at the output one sees D[0000] 01 00 10 which means applet version 1.0.10, which is the first version fixed.

Replace pins of the key

The standard pins are 123456 for the user pin, and 12345678 for the admin pin. These need immediate change!

Warning: When changing the ping the normal pin must be 6 (at least?) digits, and the admin pin 8 (at least?), other gpg2 cannot use the key anymore. No idea why.

$ gpg2 --homedir gpgtmp --card-edit
 
Reader ...........: 1050:0116:X:0
Application ID ...: D2760001240102000006036457190000
Version ..........: 2.0
Manufacturer .....: Yubico
Serial number ....: 03645719
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
 
gpg/card> admin
Admin commands are allowed
 
gpg/card> passwd
gpg: OpenPGP card no. D2760001240102000006036457190000 detected
 
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
 
Your selection? 3
PIN changed.
 
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
 
Your selection? 1
PIN changed.
 
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
 
Your selection? q
 
gpg/card> quit

After this you need to use the new pins for all changes.

Setup basic data

The key can also save some basic data about yourself, like name, sex, language preferences, login name, and url to obtain the public key. As before start gpg2 and then change these infos in the following way>

gpg/card> name
Cardholder's surname: Preining
Cardholder's given name: Norbert
 
gpg/card> sex
Sex ((M)ale, (F)emale or space): M
 
gpg/card> lang
Language preferences: de
 
gpg/card> login
Login data (account name): norbert
 
gpg/card> url
URL to retrieve public key: https://www.preining.info/preining-norbert.asc
 
gpg/card> list
 
Reader ...........: 1050:0116:X:0
Application ID ...: D2760001240102000006036457190000
Version ..........: 2.0
Manufacturer .....: Yubico
Serial number ....: 03645719
Name of cardholder: Norbert Preining
Language prefs ...: de
Sex ..............: male
URL of public key : https://www.preining.info/preining-norbert.asc
Login data .......: norbert
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
 
gpg/card> quit

Move sub keys to Yubikey

As laid out in the article on GnuPG subkeys, we are having three subkeys for signing, encryption, and authentication. In reality I will practically only use the signing key, but upload all three keys to the card. In the following I expect that you have a setup more or less similar to the one described in the article linked before.

Again, we use GnuPG v2, mostly because it was the version that worked out of the box. In addition, if you are setting up a similar stage like in my GNuPG article with gpg1 keys on the mail server, then you don’t want the gpg1 keys being removed.

Basically you must have the Yubikey plugged in and call keytocard after selecting each key in turn (and deselecting it afterwards).

Warning: There is another bug in the GnuPG applet that was fixed in later versions (but not in 1.0.10), namely that not all keys are accepted. This is a bit a pain. I needed to recreate a subkey to obtain a key that can be loaded onto the Yubikey. Unfortunately, Yubico has also stopped/disabled the ability to update applets (although I have to say their documentation is an incredible rubbish with respect to applets and upgrades …).

As before, assume that $MASTERKEY contains the hex id of your master key.

$ gpg2 --edit-key $MASTERKEY
gpg (GnuPG) 2.1.11; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
 
Secret key is available.
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 2
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb* rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb* rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 2
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 3
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb* rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb* rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 3
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 4
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb* rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> keytocard
Please select where to store the key:
   (3) Authentication key
Your selection? 3
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb* rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> key 4
 
sec  rsa4096/0x6CACA448860CDC13
     created: 2010-09-14  expires: 2017-02-06  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xD1D2BD14810F62B3
     created: 2010-09-14  expires: 2017-02-06  usage: E   
ssb  rsa2048/0xEC00B8DAD32266AA
     created: 2016-02-07  expires: 2017-02-06  usage: S   
ssb  rsa2048/0xBF361ED434425B4C
     created: 2016-02-07  expires: 2017-02-06  usage: E   
ssb  rsa2048/0x9C7CA4E294F04D49
     created: 2016-02-07  expires: 2017-02-06  usage: A   
[ultimate] (1). Norbert Preining <norbert@preining.info>
[ultimate] (2)  Norbert Preining <preining@logic.at>
[ultimate] (3)  Norbert Preining <preining@debian.org>
[ultimate] (4)  Norbert Preining <preining@jaist.ac.jp>
[ultimate] (5)  [jpeg image of size 4185]
 
gpg> save

After that your keys are on the Yubikey (and only there!), and GNuPG will require the PIN (user pin) to sign/encrypt documents.

Usage

Many things have been said above, but to sum up when and how I am using the YubiKey now:

  • Logging into my computer: I need to have the key plugged in, otherwise authentication will not succeed.
  • GPG activities (signing, encryption): Key needs to be plugged in, GnuPG will ask the User pin.
  • TOTP (Google, GitHub, WordPress, DropBox login): I use my mobile (Nexus 6p) and the Yubico Authenticator, touch the phone with the Yubikey, and see the TOTPs in the application windows.
  • OpenKeychain (Android app) – integrates with K-9 Mail – signing, encryption and decryption is possible on the mobile via NFC (touching the device with the key)

Conclusions

With this setup I am now quite content, but not completely. What I still want to do is full disk encryption where I need the Yubikey to boot – and again, with an alternative for a very long passphrase. At the end, adding a second factor to the login is not really optimal, and only protects you against quick hacks. If the laptop is actually stolen, only full disc protection helps. Access to the hardware always guarantees that one has access to everything on the disc.

Another thing I want to do is re-use the GnuPG key on the Yubikey as ssh key for logging into remote systems. That would mean that I get rid of even more keys on my laptop. But this is still in the work 😉

The other open question is what to use the other available slot of the Yubikey for? I thought about some passwords (possible), but I don’t feel to happy about having my password issued with the press of a key.

But all in all, I like the setup much more than before – and not having any GnuPG key on the laptop is a big plus.

14 Responses

  1. Ben Kibbey says:

    There is also libpam-poldi to login with a smartcard via scdaemon (gnupg). I don’t have a Yubikey but it sounds pretty cool.

    • Hi Ben,
      thanks for the hint, but the libpam-yubico already communicates with the key, so that is fine. Of course using libpam-poldi to get rid of the challenge-response and use something stronger might be a good idea. Need to check whether one can use that with alternatives. Thanks again.

      • Ben Kibbey says:

        Also I forgot to mention that gpg-agent can act as an ssh-agent so you can use a gpg key for ssh authentication. See gpg2 –export-ssh-key.

        • Yes, I have this running half way, but first need to update all the places of my SSH key, and there are far too many 😉 Also I need to find out how to extend the lifetime of the passphrase. Worth gpg-agent the passphrase of the SSH key is forgotten too soon. All to be written in a follow-up!

  2. Thanks, Norbert. Not only that the article is nicely written, but also most of the information provided is new to me and quite interesting. I do use two step authentication, but yubikey provides a newer way of achieving it and more. I will give a try 🙂 Once again many thanks for finding time to write a blog to share with general public.

  3. mirabilos says:

    Just be careful what you trust what with.

    https://twitter.com/Fr333k/status/725688432970878976 Breaking #yubikey crypto within 1h physical access, Timo Kasper at #ruhrsec …

  4. Frediz says:

    Hi Norbert,
    I’m looking for a HSM device and the issue I found with Yubikey Neo is that is doesn’t support 4096b keys as you mentionned.
    In Debian, it is advised to have such keys now, if one does not have good reason to stick to 2048b.
    How do you do to handle this ? I see you have a 4096b key, didn’t you import it to the key ? Did I miss something ?
    Also as for the Yubikey 4, it does not have an open source firmware…(contrary to the others Yubico did).
    So I’m a bit puzzled 🙂

    F.

    • Hi Frediz,
      I am having a main key of 4096bits, but subkeys with 2048bits. That is fine enough. Debian (ftp etc) accepts signatures made with both the main key as well as the signing subkey. So at least for me there is no problem.

      And I agree that the yubikey4 has no open firmware, and in addition no NFC so I cannot use it with my mobile for encryption and OTPs, so I ordered several YubiKey Neo just to stack up 😉

  5. Dmitry Dulepov says:

    I know this post is quite old but

    I am currently searching for a method to replace the second factor of they key optionally with a different authentication method

    You can have a look to this: http://github.com/dmitryd/kali-yubikey/ It is not authentication but LUKS encryption but it does a similar thing: you can use your yubikey with your password and also a backup password. The good thing is that your yubikey part of the password will change at each login as well as your encryption key, so even if somebody makes a copy of your drive without your knowledge, they can’t unlock it after your single successful login to the system. May be, you can do something like that for authentication. It should be easier than playing with boot scripts.

  1. 2016/05/17

    […] have been around for a few years, but I’ve just discovered it via a recent Nobert Preining’s blog post explaining how he secured his Debian computer, which now requires the key to login, send PGP signed […]

  2. 2016/05/19

    […] несколько лет, но я смог узнать о нём только прочитав пост в блоге Ноберта Прингса в котором он рассказывал о защите своего компьютера […]

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>