Commit Graph

1803 Commits

Author SHA1 Message Date
Herbert Xu
4e6c3df4d7 crypto: skcipher - Add low-level skcipher interface
This patch allows skcipher algorithms and instances to be created
and registered with the crypto API.  They are accessible through
the top-level skcipher interface, along with ablkcipher/blkcipher
algorithms and instances.

This patch also introduces a new parameter called chunk size
which is meant for ciphers such as CTR and CTS which ostensibly
can handle arbitrary lengths, but still behave like block ciphers
in that you can only process a partial block at the very end.

For these ciphers the block size will continue to be set to 1
as it is now while the chunk size will be set to the underlying
block size.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-18 17:35:36 +08:00
Salvatore Benedetto
c8afbc8404 crypto: testmgr - Add 4K private key to RSA testvector
Key generated with openssl. It also contains all fields required
for testing CRT mode

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-05 23:05:27 +08:00
Salvatore Benedetto
8be0b84e58 crypto: rsa - Store rest of the private key components
When parsing a private key, store all non-optional fields. These
are required for enabling CRT mode for decrypt and verify

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-05 23:05:26 +08:00
Salvatore Benedetto
57763f5ec7 crypto: testmgr - Set err before proceeding
Report correct error in case of failure

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-05 23:05:22 +08:00
Anton Blanchard
6dd7a82cc5 crypto: powerpc - Add POWER8 optimised crc32c
Use the vector polynomial multiply-sum instructions in POWER8 to
speed up crc32c.

This is just over 41x faster than the slice-by-8 method that it
replaces. Measurements on a 4.1 GHz POWER8 show it sustaining
52 GiB/sec.

A simple btrfs write performance test:

    dd if=/dev/zero of=/mnt/tmpfile bs=1M count=4096
    sync

is over 3.7x faster.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-05 23:05:19 +08:00
Herbert Xu
27710b8ea3 crypto: rsa-pkcs1pad - Fix regression from leading zeros
As the software RSA implementation now produces fixed-length
output, we need to eliminate leading zeros in the calling code
instead.

This patch does just that for pkcs1pad signature verification.

Fixes: 9b45b7bba3 ("crypto: rsa - Generate fixed-length output")
Reported-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-03 15:44:56 +08:00
raveendra padasalagi
98eca72fa0 crypto: sha3 - Add HMAC-SHA3 test modes and test vectors
This patch adds HMAC-SHA3 test modes in tcrypt module
and related test vectors.

Signed-off-by: Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:24 +08:00
Herbert Xu
d13cd11fbc crypto: tcrypt - Do not bail on EINPROGRESS in multibuffer hash test
The multibuffer hash speed test is incorrectly bailing because
of an EINPROGRESS return value.  This patch fixes it by setting
ret to zero if it is equal to -EINPROGRESS.

Reported-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:21 +08:00
Herbert Xu
d858b07138 crypto: rsa-pkcs1pad - Avoid copying output when possible
In the vast majority of cases (2^-32 on 32-bit and 2^-64 on 64-bit)
cases, the result from encryption/signing will require no padding.

This patch makes these two operations write their output directly
to the final destination.  Only in the exceedingly rare cases where
fixup is needed to we copy it out and back to add the leading zeroes.

This patch also makes use of the crypto_akcipher_set_crypt API
instead of writing the akcipher request directly.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:20 +08:00
Herbert Xu
73f7918960 crypto: rsa-pkcs1pad - Move key size check to setkey
Rather than repeatedly checking the key size on each operation,
we should be checking it once when the key is set.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:20 +08:00
Herbert Xu
3a32ce507a crypto: rsa-pkcs1pad - Always use GFP_KERNEL
We don't currently support using akcipher in atomic contexts,
so GFP_KERNEL should always be used.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:19 +08:00
Herbert Xu
0f2c83190b crypto: rsa-pkcs1pad - Remove bogus page splitting
The helper pkcs1pad_sg_set_buf tries to split a buffer that crosses
a page boundary into two SG entries.  This is unnecessary.  This
patch removes that.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:19 +08:00
Herbert Xu
c0d20d22e0 crypto: rsa-pkcs1pad - Require hash to be present
The only user of rsa-pkcs1pad always uses the hash so there is
no reason to support the case of not having a hash.

This patch also changes the digest info lookup so that it is
only done once during template instantiation rather than on each
operation.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:19 +08:00
Herbert Xu
9b45b7bba3 crypto: rsa - Generate fixed-length output
Every implementation of RSA that we have naturally generates
output with leading zeroes.  The one and only user of RSA,
pkcs1pad wants to have those leading zeroes in place, in fact
because they are currently absent it has to write those zeroes
itself.

So we shouldn't be stripping leading zeroes in the first place.
In fact this patch makes rsa-generic produce output with fixed
length so that pkcs1pad does not need to do any extra work.

This patch also changes DH to use the new interface.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:18 +08:00
Herbert Xu
50d2b643ea crypto: testmgr - Allow leading zeros in RSA
This patch allows RSA implementations to produce output with
leading zeroes.  testmgr will skip leading zeroes when comparing
the output.

This patch also tries to make the RSA test function generic enough
to potentially handle other akcipher algorithms.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:12 +08:00
Herbert Xu
1503a24f53 crypto: tcrypt - Add speed test for cts
This patch adds speed tests for cts(cbc(aes)).

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:11 +08:00
Herbert Xu
32f27c745c crypto: api - Add crypto_inst_setname
This patch adds the helper crypto_inst_setname because the current
helper crypto_alloc_instance2 is no longer useful given that we
now look up the algorithm after we allocate the instance object.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:11 +08:00
Herbert Xu
7166e589da crypto: tcrypt - Use skcipher
This patch converts tcrypt to use the new skcipher interface as
opposed to ablkcipher/blkcipher.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:04 +08:00
Herbert Xu
2495cf25f6 crypto: ahash - Add padding in crypto_ahash_extsize
The function crypto_ahash_extsize did not include padding when
computing the tfm context size.  This patch fixes this by using
the generic crypto_alg_extsize helper.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:03 +08:00
Herbert Xu
927ef32dcc crypto: authenc - Consider ahash ASYNC bit
As it is, if you get an async ahash with a sync skcipher you'll
end up with a sync authenc, which is wrong.

This patch fixes it by considering the ASYNC bit from ahash as
well.

It also fixes a little bug where if a sync version of authenc
is requested we may still end up using an async ahash.

Neither of them should have any effect as none of the authenc
users can request for a sync authenc.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-07-01 23:45:02 +08:00
Harsh Jain
c34252fd71 crypto: authenc - Remove redundant sg_init_table call.
Remove redundant sg_init_table call. scatterwalk_ffwd doing the same.

Signed-off-by: Harsh Jain <harshjain.prof@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-29 18:12:43 +08:00
Herbert Xu
72259deb3a crypto: tcrypt - Fix memory leaks/crashes in multibuffer hash speed test
This patch resolves a number of issues with the mb speed test
function:

* The tfm is never freed.
* Memory is allocated even when we're not using mb.
* When an error occurs we don't wait for completion for other requests.
* When an error occurs during allocation we may leak memory.
* The test function ignores plen but still runs for plen != blen.
* The backlog flag is incorrectly used (may crash).

This patch tries to resolve all these issues as well as making
the code consistent with the existing hash speed testing function.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
2016-06-29 18:12:42 +08:00
Herbert Xu
f8de55b625 crypto: tcrypt - Use unsigned long for mb ahash cycle counter
For the timescales we are working against there is no need to
go beyond unsigned long.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-28 16:43:40 +08:00
Krzysztof Kozlowski
f83f5b12ee crypto: tcrypt - Fix mixing printk/pr_err and obvious indentation issues
The recently added test_mb_ahash_speed() has clearly serious coding
style issues. Try to fix some of them:
1. Don't mix pr_err() and printk();
2. Don't wrap strings;
3. Properly align goto statement in if() block;
4. Align wrapped arguments on new line;
5. Don't wrap functions on first argument;

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-28 16:06:41 +08:00
Megha Dey
14009c4bde crypto: tcrypt - Add new mode for sha512_mb
Add a new mode to calculate the speed of the sha512_mb algorithm

Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Reviewed-by: Fenghua Yu <fenghua.yu@intel.com>
Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-28 16:06:41 +08:00
Megha Dey
026bb8aaf5 crypto: sha512-mb - Enable SHA512 multibuffer support
Add the config CRYPTO_SHA512_MB which will enable the computation
using the SHA512 multi-buffer algorithm.

Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Reviewed-by: Fenghua Yu <fenghua.yu@intel.com>
Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-28 16:06:37 +08:00
Megha Dey
087bcd225c crypto: tcrypt - Add speed tests for SHA multibuffer algorithms
The existing test suite to calculate the speed of the SHA algorithms
assumes serial (single buffer)) computation of data. With the SHA
multibuffer algorithms, we work on 8 lanes of data in parallel. Hence,
the need to introduce a new test suite to calculate the speed for these
algorithms.

Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-27 16:57:46 +08:00
Megha Dey
9be7e24483 crypto: sha256-mb - Enable multibuffer support
Add the config CRYPTO_SHA256_MB which will enable the computation using the
SHA256 multi-buffer algorithm.

Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Reviewed-by: Fenghua Yu <fenghua.yu@intel.com>
Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-27 16:57:43 +08:00
Stephen Rothwell
8f44df154d crypto: ecdh - make ecdh_shared_secret unique
There is another ecdh_shared_secret in net/bluetooth/ecc.c

Fixes: 3c4b23901a ("crypto: ecdh - Add ECDH software support")
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-24 21:24:59 +08:00
Stephan Mueller
b578456c34 crypto: jitterentropy - use ktime_get_ns as fallback
As part of the Y2038 development, __getnstimeofday is not supposed to be
used any more. It is now replaced with ktime_get_ns. The Jitter RNG uses
the time stamp to measure the execution time of a given code path and
tries to detect variations in the execution time. Therefore, the only
requirement the Jitter RNG has, is a sufficient high resolution to
detect these variations.

The change was tested on x86 to show an identical behavior as RDTSC. The
used test code simply measures the execution time of the heart of the
RNG:

        jent_get_nstime(&time);
        jent_memaccess(ec, min);
        jent_fold_time(NULL, time, &folded, min);
        jent_get_nstime(&time2);
        return ((time2 - time));

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-24 21:24:58 +08:00
Salvatore Benedetto
3c4b23901a crypto: ecdh - Add ECDH software support
* Implement ECDH under kpp API
 * Provide ECC software support for curve P-192 and
   P-256.
 * Add kpp test for ECDH with data generated by OpenSSL

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:57 +08:00
Salvatore Benedetto
802c7f1c84 crypto: dh - Add DH software implementation
* Implement MPI based Diffie-Hellman under kpp API
 * Test provided uses data generad by OpenSSL

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:56 +08:00
Salvatore Benedetto
4e5f2c4007 crypto: kpp - Key-agreement Protocol Primitives API (KPP)
Add key-agreement protocol primitives (kpp) API which allows to
implement primitives required by protocols such as DH and ECDH.
The API is composed mainly by the following functions
 * set_secret() - It allows the user to set his secret, also
   referred to as his private key, along with the parameters
   known to both parties involved in the key-agreement session.
 * generate_public_key() - It generates the public key to be sent to
   the other counterpart involved in the key-agreement session. The
   function has to be called after set_params() and set_secret()
 * generate_secret() - It generates the shared secret for the session

Other functions such as init() and exit() are provided for allowing
cryptographic hardware to be inizialized properly before use

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:56 +08:00
Megha Dey
331bf739c4 crypto: sha1-mb - async implementation for sha1-mb
Herbert wants the sha1-mb algorithm to have an async implementation:
https://lkml.org/lkml/2016/4/5/286.
Currently, sha1-mb uses an async interface for the outer algorithm
and a sync interface for the inner algorithm. This patch introduces
a async interface for even the inner algorithm.

Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:55 +08:00
Herbert Xu
88407a39b5 crypto: ablk_helper - Fix cryptd reordering
This patch fixes an old bug where requests can be reordered because
some are processed by cryptd while others are processed directly
in softirq context.

The fix is to always postpone to cryptd if there are currently
requests outstanding from the same tfm.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:53 +08:00
Herbert Xu
81760ea6a9 crypto: cryptd - Add helpers to check whether a tfm is queued
This patch adds helpers to check whether a given tfm is currently
queued.  This is meant to be used by ablk_helper and similar
entities to ensure that no reordering is introduced because of
requests queued in cryptd with respect to requests being processed
in softirq context.

The per-cpu queue length limit is also increased to 1000 in line
with network limits.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:29:52 +08:00
Herbert Xu
fd2efd93b6 Revert "crypto: user - no parsing of CRYPTO_MSG_GETALG"
This patch commit eed1e1afd8 as
it is only a workaround for the real bug and the proper fix has
now been applied as 055ddaace0
("crypto: user - re-add size check for CRYPTO_MSG_GETALG").

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-23 18:06:02 +08:00
Dan Carpenter
01ac94580a crypto: drbg - fix an error code in drbg_init_sym_kernel()
We accidentally return PTR_ERR(NULL) which is success but we should
return -ENOMEM.

Fixes: 3559128521 ('crypto: drbg - use CTR AES instead of ECB AES')
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-20 19:25:03 +08:00
raveendra padasalagi
79cc6ab894 crypto: sha3 - Add SHA-3 Test's in tcrypt
Added support for SHA-3 algorithm test's
in tcrypt module and related test vectors.

Signed-off-by: Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-20 19:25:02 +08:00
Jeff Garzik
53964b9ee6 crypto: sha3 - Add SHA-3 hash algorithm
This patch adds the implementation of SHA3 algorithm
in software and it's based on original implementation
pushed in patch https://lwn.net/Articles/518415/ with
additional changes to match the padding rules specified
in SHA-3 specification.

Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-20 19:25:01 +08:00
Herbert Xu
b30bdfa864 crypto: gcm - Filter out async ghash if necessary
As it is if you ask for a sync gcm you may actually end up with
an async one because it does not filter out async implementations
of ghash.

This patch fixes this by adding the necessary filter when looking
for ghash.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-20 19:24:37 +08:00
Wu Fengguang
88f1d316b9 crypto: drbg - fix semicolon.cocci warnings
crypto/drbg.c:1637:39-40: Unneeded semicolon

 Remove unneeded semicolon.

Generated by: scripts/coccinelle/misc/semicolon.cocci

CC: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
Acked-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-20 19:24:36 +08:00
Tudor Ambarus
5a7de97309 crypto: rsa - return raw integers for the ASN.1 parser
Return the raw key with no other processing so that the caller
can copy it or MPI parse it, etc.

The scope is to have only one ANS.1 parser for all RSA
implementations.

Update the RSA software implementation so that it does
the MPI conversion on top.

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-15 17:07:54 +08:00
Stephan Mueller
103eb3f7bf crypto: drbg - avoid duplicate maintenance of key
The TFM object maintains the key for the CTR DRBG.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-15 17:07:54 +08:00
Stephan Mueller
a07203fbfc crypto: drbg - use full CTR AES for update
The CTR DRBG update function performs a full CTR AES operation including
the XOR with "plaintext" data. Hence, remove the XOR from the code and
use the CTR mode to do the XOR.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-15 17:07:53 +08:00
Stephan Mueller
3cfc3b9721 crypto: drbg - use aligned buffers
Hardware cipher implementation may require aligned buffers. All buffers
that potentially are processed with a cipher are now aligned.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-15 17:07:53 +08:00
Stephan Mueller
3559128521 crypto: drbg - use CTR AES instead of ECB AES
The CTR DRBG derives its random data from the CTR that is encrypted with
AES.

This patch now changes the CTR DRBG implementation such that the
CTR AES mode is employed. This allows the use of steamlined CTR AES
implementation such as ctr-aes-aesni.

Unfortunately there are the following subtile changes we need to apply
when using the CTR AES mode:

- the CTR mode increments the counter after the cipher operation, but
  the CTR DRBG requires the increment before the cipher op. Hence, the
  crypto_inc is applied to the counter (drbg->V) once it is
  recalculated.

- the CTR mode wants to encrypt data, but the CTR DRBG is interested in
  the encrypted counter only. The full CTR mode is the XOR of the
  encrypted counter with the plaintext data. To access the encrypted
  counter, the patch uses a NULL data vector as plaintext to be
  "encrypted".

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-15 17:07:53 +08:00
Geliang Tang
88aff46040 crypto: skcipher - remove unused header cpumask.h
Remove unused header cpumask.h from crypto/ablkcipher.c.

Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-07 18:41:53 +08:00
Stephan Mueller
ed494d4fa2 crypto: drbg - reduce number of setkey calls
The CTR DRBG code always set the key for each sym cipher invocation even
though the key has not been changed.

The patch ensures that the setkey is only invoked when a new key is
generated by the DRBG.

With this patch, the CTR DRBG performance increases by more than 150%.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-06-02 18:39:01 +08:00
Stephan Mueller
eed1e1afd8 crypto: user - no parsing of CRYPTO_MSG_GETALG
The CRYPTO_MSG_GETALG netlink message type provides a buffer to the
kernel to retrieve information from the kernel. The data buffer will not
provide any input and will not be read. Hence the nlmsg_parse is not
applicable to this netlink message type.

This patch fixes the following kernel log message when using this
netlink interface:

netlink: 208 bytes leftover after parsing attributes in process `XXX'.

Patch successfully tested with libkcapi from [1] which uses
CRYPTO_MSG_GETALG to obtain cipher-specific information from the kernel.

[1] http://www.chronox.de/libkcapi.html

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2016-05-31 16:41:47 +08:00