diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Kconfig | 17 | ||||
-rw-r--r-- | crypto/Makefile | 10 | ||||
-rw-r--r-- | crypto/ablkcipher.c | 2 | ||||
-rw-r--r-- | crypto/ahash.c | 3 | ||||
-rw-r--r-- | crypto/akcipher.c | 1 | ||||
-rw-r--r-- | crypto/algapi.c | 2 | ||||
-rw-r--r-- | crypto/api.c | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_keys.h | 5 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 44 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 5 | ||||
-rw-r--r-- | crypto/asymmetric_keys/public_key.c | 4 | ||||
-rw-r--r-- | crypto/asymmetric_keys/signature.c | 2 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 18 | ||||
-rw-r--r-- | crypto/crypto_user.c | 2 | ||||
-rw-r--r-- | crypto/jitterentropy-kcapi.c | 4 | ||||
-rw-r--r-- | crypto/keywrap.c | 419 | ||||
-rw-r--r-- | crypto/rsa.c | 83 | ||||
-rw-r--r-- | crypto/rsa_helper.c | 42 | ||||
-rw-r--r-- | crypto/rsakey.asn1 | 5 | ||||
-rw-r--r-- | crypto/rsaprivkey.asn1 | 11 | ||||
-rw-r--r-- | crypto/rsapubkey.asn1 | 4 | ||||
-rw-r--r-- | crypto/skcipher.c | 4 | ||||
-rw-r--r-- | crypto/tcrypt.c | 17 | ||||
-rw-r--r-- | crypto/testmgr.c | 83 | ||||
-rw-r--r-- | crypto/testmgr.h | 77 |
27 files changed, 720 insertions, 157 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index 48ee3e1..7240821 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -348,6 +348,13 @@ config CRYPTO_XTS key size 256, 384 or 512 bits. This implementation currently can't handle a sectorsize which is not a multiple of 16 bytes. +config CRYPTO_KEYWRAP + tristate "Key wrapping support" + select CRYPTO_BLKCIPHER + help + Support for key wrapping (NIST SP800-38F / RFC3394) without + padding. + comment "Hash modes" config CRYPTO_CMAC @@ -597,17 +604,18 @@ config CRYPTO_SHA1 SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). config CRYPTO_SHA1_SSSE3 - tristate "SHA1 digest algorithm (SSSE3/AVX/AVX2)" + tristate "SHA1 digest algorithm (SSSE3/AVX/AVX2/SHA-NI)" depends on X86 && 64BIT select CRYPTO_SHA1 select CRYPTO_HASH help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented using Supplemental SSE3 (SSSE3) instructions or Advanced Vector - Extensions (AVX/AVX2), when available. + Extensions (AVX/AVX2) or SHA-NI(SHA Extensions New Instructions), + when available. config CRYPTO_SHA256_SSSE3 - tristate "SHA256 digest algorithm (SSSE3/AVX/AVX2)" + tristate "SHA256 digest algorithm (SSSE3/AVX/AVX2/SHA-NI)" depends on X86 && 64BIT select CRYPTO_SHA256 select CRYPTO_HASH @@ -615,7 +623,8 @@ config CRYPTO_SHA256_SSSE3 SHA-256 secure hash standard (DFIPS 180-2) implemented using Supplemental SSE3 (SSSE3) instructions, or Advanced Vector Extensions version 1 (AVX1), or Advanced Vector Extensions - version 2 (AVX2) instructions, when available. + version 2 (AVX2) instructions, or SHA-NI (SHA Extensions New + Instructions) when available. config CRYPTO_SHA512_SSSE3 tristate "SHA512 digest algorithm (SSSE3/AVX/AVX2)" diff --git a/crypto/Makefile b/crypto/Makefile index e2c5981..f7aba92 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -31,10 +31,13 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o -$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h -clean-files += rsakey-asn1.c rsakey-asn1.h +$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h +$(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h +clean-files += rsapubkey-asn1.c rsapubkey-asn1.h +clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h -rsa_generic-y := rsakey-asn1.o +rsa_generic-y := rsapubkey-asn1.o +rsa_generic-y += rsaprivkey-asn1.o rsa_generic-y += rsa.o rsa_generic-y += rsa_helper.o obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o @@ -67,6 +70,7 @@ obj-$(CONFIG_CRYPTO_CTS) += cts.o obj-$(CONFIG_CRYPTO_LRW) += lrw.o obj-$(CONFIG_CRYPTO_XTS) += xts.o obj-$(CONFIG_CRYPTO_CTR) += ctr.o +obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o obj-$(CONFIG_CRYPTO_GCM) += gcm.o obj-$(CONFIG_CRYPTO_CCM) += ccm.o obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index b788f16..b4ffc5b 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -706,7 +706,7 @@ struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name, err: if (err != -EAGAIN) break; - if (signal_pending(current)) { + if (fatal_signal_pending(current)) { err = -EINTR; break; } diff --git a/crypto/ahash.c b/crypto/ahash.c index 8acb88603..9c1dc8d 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -544,7 +544,8 @@ static int ahash_prepare_alg(struct ahash_alg *alg) struct crypto_alg *base = &alg->halg.base; if (alg->halg.digestsize > PAGE_SIZE / 8 || - alg->halg.statesize > PAGE_SIZE / 8) + alg->halg.statesize > PAGE_SIZE / 8 || + alg->halg.statesize == 0) return -EINVAL; base->cra_type = &crypto_ahash_type; diff --git a/crypto/akcipher.c b/crypto/akcipher.c index 528ae6a..120ec04 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -21,7 +21,6 @@ #include <linux/cryptouser.h> #include <net/netlink.h> #include <crypto/akcipher.h> -#include <crypto/public_key.h> #include "internal.h" #ifdef CONFIG_NET diff --git a/crypto/algapi.c b/crypto/algapi.c index d130b41..59bf491 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -345,7 +345,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval) crypto_alg_tested(larval->alg.cra_driver_name, 0); } - err = wait_for_completion_interruptible(&larval->completion); + err = wait_for_completion_killable(&larval->completion); WARN_ON(err); out: diff --git a/crypto/api.c b/crypto/api.c index afe4610..bbc147c 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -172,7 +172,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) struct crypto_larval *larval = (void *)alg; long timeout; - timeout = wait_for_completion_interruptible_timeout( + timeout = wait_for_completion_killable_timeout( &larval->completion, 60 * HZ); alg = larval->adult; @@ -445,7 +445,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) err: if (err != -EAGAIN) break; - if (signal_pending(current)) { + if (fatal_signal_pending(current)) { err = -EINTR; break; } @@ -562,7 +562,7 @@ void *crypto_alloc_tfm(const char *alg_name, err: if (err != -EAGAIN) break; - if (signal_pending(current)) { + if (fatal_signal_pending(current)) { err = -EINTR; break; } diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h index 3f5b537..1d450b5 100644 --- a/crypto/asymmetric_keys/asymmetric_keys.h +++ b/crypto/asymmetric_keys/asymmetric_keys.h @@ -14,8 +14,3 @@ extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); extern int __asymmetric_key_hex_to_key_id(const char *id, struct asymmetric_key_id *match_id, size_t hexlen); -static inline -const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) -{ - return key->type_data.p[1]; -} diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 1916680..9f2165b 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -307,25 +307,34 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep) } /* + * Clean up the key ID list + */ +static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) +{ + int i; + + if (kids) { + for (i = 0; i < ARRAY_SIZE(kids->id); i++) + kfree(kids->id[i]); + kfree(kids); + } +} + +/* * Clean up the preparse data */ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) { - struct asymmetric_key_subtype *subtype = prep->type_data[0]; - struct asymmetric_key_ids *kids = prep->type_data[1]; - int i; + struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype]; + struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids]; pr_devel("==>%s()\n", __func__); if (subtype) { - subtype->destroy(prep->payload[0]); + subtype->destroy(prep->payload.data[asym_crypto]); module_put(subtype->owner); } - if (kids) { - for (i = 0; i < ARRAY_SIZE(kids->id); i++) - kfree(kids->id[i]); - kfree(kids); - } + asymmetric_key_free_kids(kids); kfree(prep->description); } @@ -335,20 +344,19 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) static void asymmetric_key_destroy(struct key *key) { struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); - struct asymmetric_key_ids *kids = key->type_data.p[1]; + struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids]; + void *data = key->payload.data[asym_crypto]; + + key->payload.data[asym_crypto] = NULL; + key->payload.data[asym_subtype] = NULL; + key->payload.data[asym_key_ids] = NULL; if (subtype) { - subtype->destroy(key->payload.data); + subtype->destroy(data); module_put(subtype->owner); - key->type_data.p[0] = NULL; } - if (kids) { - kfree(kids->id[0]); - kfree(kids->id[1]); - kfree(kids); - key->type_data.p[1] = NULL; - } + asymmetric_key_free_kids(kids); } struct key_type key_type_asymmetric = { diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index d20c0b4..325575c 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -49,11 +49,12 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm); ret = -ENOMEM; - digest = kzalloc(digest_size + desc_size, GFP_KERNEL); + digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, + GFP_KERNEL); if (!digest) goto error_no_desc; - desc = digest + digest_size; + desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc)); desc->tfm = tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 81efccb..6db4c01 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -49,7 +49,7 @@ EXPORT_SYMBOL_GPL(pkey_id_type_name); static void public_key_describe(const struct key *asymmetric_key, struct seq_file *m) { - struct public_key *key = asymmetric_key->payload.data; + struct public_key *key = asymmetric_key->payload.data[asym_crypto]; if (key) seq_printf(m, "%s.%s", @@ -112,7 +112,7 @@ EXPORT_SYMBOL_GPL(public_key_verify_signature); static int public_key_verify_signature_2(const struct key *key, const struct public_key_signature *sig) { - const struct public_key *pk = key->payload.data; + const struct public_key *pk = key->payload.data[asym_crypto]; return public_key_verify_signature(pk, sig); } diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c index 7525fd1..9441240 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c @@ -37,7 +37,7 @@ int verify_signature(const struct key *key, return -EINVAL; subtype = asymmetric_key_subtype(key); if (!subtype || - !key->payload.data) + !key->payload.data[0]) return -EINVAL; if (!subtype->verify_signature) return -ENOTSUPP; diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index af71878..3000ea3 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -546,9 +546,9 @@ int x509_decode_time(time64_t *_t, size_t hdrlen, if (year < 1970 || mon < 1 || mon > 12 || day < 1 || day > mon_len || - hour < 0 || hour > 23 || - min < 0 || min > 59 || - sec < 0 || sec > 59) + hour > 23 || + min > 59 || + sec > 59) goto invalid_time; *_t = mktime64(year, mon, day, hour, min, sec); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 1de01ea..dbeed60 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -11,6 +11,7 @@ #include <linux/time.h> #include <crypto/public_key.h> +#include <keys/asymmetric-type.h> struct x509_certificate { struct x509_certificate *next; diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 6d88dd1..2a44b37 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -194,14 +194,15 @@ int x509_get_sig_params(struct x509_certificate *cert) * digest storage space. */ ret = -ENOMEM; - digest = kzalloc(digest_size + desc_size, GFP_KERNEL); + digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size, + GFP_KERNEL); if (!digest) goto error; cert->sig.digest = digest; cert->sig.digest_size = digest_size; - desc = digest + digest_size; + desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc)); desc->tfm = tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; @@ -266,7 +267,8 @@ static int x509_validate_trust(struct x509_certificate *cert, if (!IS_ERR(key)) { if (!use_builtin_keys || test_bit(KEY_FLAG_BUILTIN, &key->flags)) - ret = x509_check_signature(key->payload.data, cert); + ret = x509_check_signature(key->payload.data[asym_crypto], + cert); key_put(key); } return ret; @@ -332,10 +334,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) srlen = cert->raw_serial_size; q = cert->raw_serial; } - if (srlen > 1 && *q == 0) { - srlen--; - q++; - } ret = -ENOMEM; desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); @@ -356,9 +354,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) /* We're pinning the module by being linked against it */ __module_get(public_key_subtype.owner); - prep->type_data[0] = &public_key_subtype; - prep->type_data[1] = kids; - prep->payload[0] = cert->pub; + prep->payload.data[asym_subtype] = &public_key_subtype; + prep->payload.data[asym_key_ids] = kids; + prep->payload.data[asym_crypto] = cert->pub; prep->description = desc; prep->quotalen = 100; diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index d94d99f..237f379 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -375,7 +375,7 @@ static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, err = PTR_ERR(alg); if (err != -EAGAIN) break; - if (signal_pending(current)) { + if (fatal_signal_pending(current)) { err = -EINTR; break; } diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c index ceea83d..597cedd 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -98,10 +98,6 @@ void jent_get_nstime(__u64 *out) * If random_get_entropy does not return a value (which is possible on, * for example, MIPS), invoke __getnstimeofday * hoping that there are timers we can work with. - * - * The list of available timers can be obtained from - * /sys/devices/system/clocksource/clocksource0/available_clocksource - * and are registered with clocksource_register() */ if ((0 == tmp) && (0 == __getnstimeofday(&ts))) { diff --git a/crypto/keywrap.c b/crypto/keywrap.c new file mode 100644 index 0000000..b1d106c --- /dev/null +++ b/crypto/keywrap.c @@ -0,0 +1,419 @@ +/* + * Key Wrapping: RFC3394 / NIST SP800-38F + * + * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU General Public License, in which case the provisions of the GPL2 + * are required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +/* + * Note for using key wrapping: + * + * * The result of the encryption operation is the ciphertext starting + * with the 2nd semiblock. The first semiblock is provided as the IV. + * The IV used to start the encryption operation is the default IV. + * + * * The input for the decryption is the first semiblock handed in as an + * IV. The ciphertext is the data starting with the 2nd semiblock. The + * return code of the decryption operation will be EBADMSG in case an + * integrity error occurs. + * + * To obtain the full result of an encryption as expected by SP800-38F, the + * caller must allocate a buffer of plaintext + 8 bytes: + * + * unsigned int datalen = ptlen + crypto_skcipher_ivsize(tfm); + * u8 data[datalen]; + * u8 *iv = data; + * u8 *pt = data + crypto_skcipher_ivsize(tfm); + * <ensure that pt contains the plaintext of size ptlen> + * sg_init_one(&sg, ptdata, ptlen); + * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); + * + * ==> After encryption, data now contains full KW result as per SP800-38F. + * + * In case of decryption, ciphertext now already has the expected length + * and must be segmented appropriately: + * + * unsigned int datalen = CTLEN; + * u8 data[datalen]; + * <ensure that data contains full ciphertext> + * u8 *iv = data; + * u8 *ct = data + crypto_skcipher_ivsize(tfm); + * unsigned int ctlen = datalen - crypto_skcipher_ivsize(tfm); + * sg_init_one(&sg, ctdata, ctlen); + * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); + * + * ==> After decryption (which hopefully does not return EBADMSG), the ct + * pointer now points to the plaintext of size ctlen. + * + * Note 2: KWP is not implemented as this would defy in-place operation. + * If somebody wants to wrap non-aligned data, he should simply pad + * the input with zeros to fill it up to the 8 byte boundary. + */ + +#include <linux/module.h> +#include <linux/crypto.h> +#include <linux/scatterlist.h> +#include <crypto/scatterwalk.h> +#include <crypto/internal/skcipher.h> + +struct crypto_kw_ctx { + struct crypto_cipher *child; +}; + +struct crypto_kw_block { +#define SEMIBSIZE 8 + u8 A[SEMIBSIZE]; + u8 R[SEMIBSIZE]; +}; + +/* convert 64 bit integer into its string representation */ +static inline void crypto_kw_cpu_to_be64(u64 val, u8 *buf) +{ + __be64 *a = (__be64 *)buf; + + *a = cpu_to_be64(val); +} + +/* + * Fast forward the SGL to the "end" length minus SEMIBSIZE. + * The start in the SGL defined by the fast-forward is returned with + * the walk variable + */ +static void crypto_kw_scatterlist_ff(struct scatter_walk *walk, + struct scatterlist *sg, + unsigned int end) +{ + unsigned int skip = 0; + + /* The caller should only operate on full SEMIBLOCKs. */ + BUG_ON(end < SEMIBSIZE); + + skip = end - SEMIBSIZE; + while (sg) { + if (sg->length > skip) { + scatterwalk_start(walk, sg); + scatterwalk_advance(walk, skip); + break; + } else + skip -= sg->length; + + sg = sg_next(sg); + } +} + +static int crypto_kw_decrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct crypto_blkcipher *tfm = desc->tfm; + struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); + struct crypto_cipher *child = ctx->child; + + unsigned long alignmask = max_t(unsigned long, SEMIBSIZE, + crypto_cipher_alignmask(child)); + unsigned int i; + + u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask]; + struct crypto_kw_block *block = (struct crypto_kw_block *) + PTR_ALIGN(blockbuf + 0, alignmask + 1); + + u64 t = 6 * ((nbytes) >> 3); + struct scatterlist *lsrc, *ldst; + int ret = 0; + + /* + * Require at least 2 semiblocks (note, the 3rd semiblock that is + * required by SP800-38F is the IV. + */ + if (nbytes < (2 * SEMIBSIZE) || nbytes % SEMIBSIZE) + return -EINVAL; + + /* Place the IV into block A */ + memcpy(block->A, desc->info, SEMIBSIZE); + + /* + * src scatterlist is read-only. dst scatterlist is r/w. During the + * first loop, lsrc points to src and ldst to dst. For any + * subsequent round, the code operates on dst only. + */ + lsrc = src; + ldst = dst; + + for (i = 0; i < 6; i++) { + u8 tbe_buffer[SEMIBSIZE + alignmask]; + /* alignment for the crypto_xor and the _to_be64 operation */ + u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1); + unsigned int tmp_nbytes = nbytes; + struct scatter_walk src_walk, dst_walk; + + while (tmp_nbytes) { + /* move pointer by tmp_nbytes in the SGL */ + crypto_kw_scatterlist_ff(&src_walk, lsrc, tmp_nbytes); + /* get the source block */ + scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE, + false); + + /* perform KW operation: get counter as byte string */ + crypto_kw_cpu_to_be64(t, tbe); + /* perform KW operation: modify IV with counter */ + crypto_xor(block->A, tbe, SEMIBSIZE); + t--; + /* perform KW operation: decrypt block */ + crypto_cipher_decrypt_one(child, (u8*)block, + (u8*)block); + + /* move pointer by tmp_nbytes in the SGL */ + crypto_kw_scatterlist_ff(&dst_walk, ldst, tmp_nbytes); + /* Copy block->R into place */ + scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE, + true); + + tmp_nbytes -= SEMIBSIZE; + } + + /* we now start to operate on the dst SGL only */ + lsrc = dst; + ldst = dst; + } + + /* Perform authentication check */ + if (crypto_memneq("\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", block->A, + SEMIBSIZE)) + ret = -EBADMSG; + + memzero_explicit(&block, sizeof(struct crypto_kw_block)); + + return ret; +} + +static int crypto_kw_encrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct crypto_blkcipher *tfm = desc->tfm; + struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); + struct crypto_cipher *child = ctx->child; + + unsigned long alignmask = max_t(unsigned long, SEMIBSIZE, + crypto_cipher_alignmask(child)); + unsigned int i; + + u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask]; + struct crypto_kw_block *block = (struct crypto_kw_block *) + PTR_ALIGN(blockbuf + 0, alignmask + 1); + + u64 t = 1; + struct scatterlist *lsrc, *ldst; + + /* + * Require at least 2 semiblocks (note, the 3rd semiblock that is + * required by SP800-38F is the IV that occupies the first semiblock. + * This means that the dst memory must be one semiblock larger than src. + * Also ensure that the given data is aligned to semiblock. + */ + if (nbytes < (2 * SEMIBSIZE) || nbytes % SEMIBSIZE) + return -EINVAL; + + /* + * Place the predefined IV into block A -- for encrypt, the caller + * does not need to provide an IV, but he needs to fetch the final IV. + */ + memcpy(block->A, "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", SEMIBSIZE); + + /* + * src scatterlist is read-only. dst scatterlist is r/w. During the + * first loop, lsrc points to src and ldst to dst. For any + * subsequent round, the code operates on dst only. + */ + lsrc = src; + ldst = dst; + + for (i = 0; i < 6; i++) { + u8 tbe_buffer[SEMIBSIZE + alignmask]; + u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1); + unsigned int tmp_nbytes = nbytes; + struct scatter_walk src_walk, dst_walk; + + scatterwalk_start(&src_walk, lsrc); + scatterwalk_start(&dst_walk, ldst); + + while (tmp_nbytes) { + /* get the source block */ + scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE, + false); + + /* perform KW operation: encrypt block */ + crypto_cipher_encrypt_one(child, (u8 *)block, + (u8 *)block); + /* perform KW operation: get counter as byte string */ + crypto_kw_cpu_to_be64(t, tbe); + /* perform KW operation: modify IV with counter */ + crypto_xor(block->A, tbe, SEMIBSIZE); + t++; + + /* Copy block->R into place */ + scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE, + true); + + tmp_nbytes -= SEMIBSIZE; + } + + /* we now start to operate on the dst SGL only */ + lsrc = dst; + ldst = dst; + } + + /* establish the IV for the caller to pick up */ + memcpy(desc->info, block->A, SEMIBSIZE); + + memzero_explicit(&block, sizeof(struct crypto_kw_block)); + + return 0; +} + +static int crypto_kw_setkey(struct crypto_tfm *parent, const u8 *key, + unsigned int keylen) +{ + struct crypto_kw_ctx *ctx = crypto_tfm_ctx(parent); + struct crypto_cipher *child = ctx->child; + int err; + + crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & + CRYPTO_TFM_REQ_MASK); + err = crypto_cipher_setkey(child, key, keylen); + crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & + CRYPTO_TFM_RES_MASK); + return err; +} + +static int crypto_kw_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); + struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_kw_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_cipher *cipher; + + cipher = crypto_spawn_cipher(spawn); + if (IS_ERR(cipher)) + return PTR_ERR(cipher); + + ctx->child = cipher; + return 0; +} + +static void crypto_kw_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_kw_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(ctx->child); +} + +static struct crypto_instance *crypto_kw_alloc(struct rtattr **tb) +{ + struct crypto_instance *inst = NULL; + struct crypto_alg *alg = NULL; + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); + if (err) + return ERR_PTR(err); + + alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK); + if (IS_ERR(alg)) + return ERR_CAST(alg); + + inst = ERR_PTR(-EINVAL); + /* Section 5.1 requirement for KW */ + if (alg->cra_blocksize != sizeof(struct crypto_kw_block)) + goto err; + + inst = crypto_alloc_instance("kw", alg); + if (IS_ERR(inst)) + goto err; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; + inst->alg.cra_priority = alg->cra_priority; + inst->alg.cra_blocksize = SEMIBSIZE; + inst->alg.cra_alignmask = 0; + inst->alg.cra_type = &crypto_blkcipher_type; + inst->alg.cra_blkcipher.ivsize = SEMIBSIZE; + inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; + inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; + + inst->alg.cra_ctxsize = sizeof(struct crypto_kw_ctx); + + inst->alg.cra_init = crypto_kw_init_tfm; + inst->alg.cra_exit = crypto_kw_exit_tfm; + + inst->alg.cra_blkcipher.setkey = crypto_kw_setkey; + inst->alg.cra_blkcipher.encrypt = crypto_kw_encrypt; + inst->alg.cra_blkcipher.decrypt = crypto_kw_decrypt; + +err: + crypto_mod_put(alg); + return inst; +} + +static void crypto_kw_free(struct crypto_instance *inst) +{ + crypto_drop_spawn(crypto_instance_ctx(inst)); + kfree(inst); +} + +static struct crypto_template crypto_kw_tmpl = { + .name = "kw", + .alloc = crypto_kw_alloc, + .free = crypto_kw_free, + .module = THIS_MODULE, +}; + +static int __init crypto_kw_init(void) +{ + return crypto_register_template(&crypto_kw_tmpl); +} + +static void __exit crypto_kw_exit(void) +{ + crypto_unregister_template(&crypto_kw_tmpl); +} + +module_init(crypto_kw_init); +module_exit(crypto_kw_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); +MODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)"); +MODULE_ALIAS_CRYPTO("kw"); diff --git a/crypto/rsa.c b/crypto/rsa.c index 466003e..1093e04 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -97,24 +97,21 @@ static int rsa_enc(struct akcipher_request *req) goto err_free_c; } - m = mpi_read_raw_data(req->src, req->src_len); - if (!m) { - ret = -ENOMEM; + ret = -ENOMEM; + m = mpi_read_raw_from_sgl(req->src, req->src_len); + if (!m) goto err_free_c; - } ret = _rsa_enc(pkey, c, m); if (ret) goto err_free_m; - ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len, &sign); + ret = mpi_write_to_sgl(c, req->dst, &req->dst_len, &sign); if (ret) goto err_free_m; - if (sign < 0) { + if (sign < 0) ret = -EBADMSG; - goto err_free_m; - } err_free_m: mpi_free(m); @@ -145,25 +142,21 @@ static int rsa_dec(struct akcipher_request *req) goto err_free_m; } - c = mpi_read_raw_data(req->src, req->src_len); - if (!c) { - ret = -ENOMEM; + ret = -ENOMEM; + c = mpi_read_raw_from_sgl(req->src, req->src_len); + if (!c) goto err_free_m; - } ret = _rsa_dec(pkey, m, c); if (ret) goto err_free_c; - ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); + ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign); if (ret) goto err_free_c; - if (sign < 0) { + if (sign < 0) ret = -EBADMSG; - goto err_free_c; - } - err_free_c: mpi_free(c); err_free_m: @@ -193,24 +186,21 @@ static int rsa_sign(struct akcipher_request *req) goto err_free_s; } - m = mpi_read_raw_data(req->src, req->src_len); - if (!m) { - ret = -ENOMEM; + ret = -ENOMEM; + m = mpi_read_raw_from_sgl(req->src, req->src_len); + if (!m) goto err_free_s; - } ret = _rsa_sign(pkey, s, m); if (ret) goto err_free_m; - ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len, &sign); + ret = mpi_write_to_sgl(s, req->dst, &req->dst_len, &sign); if (ret) goto err_free_m; - if (sign < 0) { + if (sign < 0) ret = -EBADMSG; - goto err_free_m; - } err_free_m: mpi_free(m); @@ -241,7 +231,8 @@ static int rsa_verify(struct akcipher_request *req) goto err_free_m; } - s = mpi_read_raw_data(req->src, req->src_len); + ret = -ENOMEM; + s = mpi_read_raw_from_sgl(req->src, req->src_len); if (!s) { ret = -ENOMEM; goto err_free_m; @@ -251,14 +242,12 @@ static int rsa_verify(struct akcipher_request *req) if (ret) goto err_free_s; - ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); + ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign); if (ret) goto err_free_s; - if (sign < 0) { + if (sign < 0) ret = -EBADMSG; - goto err_free_s; - } err_free_s: mpi_free(s); @@ -282,13 +271,13 @@ static int rsa_check_key_length(unsigned int len) return -EINVAL; } -static int rsa_setkey(struct crypto_akcipher *tfm, const void *key, - unsigned int keylen) +static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) { struct rsa_key *pkey = akcipher_tfm_ctx(tfm); int ret; - ret = rsa_parse_key(pkey, key, keylen); + ret = rsa_parse_pub_key(pkey, key, keylen); if (ret) return ret; @@ -299,6 +288,30 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const void *key, return ret; } +static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct rsa_key *pkey = akcipher_tfm_ctx(tfm); + int ret; + + ret = rsa_parse_priv_key(pkey, key, keylen); + if (ret) + return ret; + + if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) { + rsa_free_key(pkey); + ret = -EINVAL; + } + return ret; +} + +static int rsa_max_size(struct crypto_akcipher *tfm) +{ + struct rsa_key *pkey = akcipher_tfm_ctx(tfm); + + return pkey->n ? mpi_get_size(pkey->n) : -EINVAL; +} + static void rsa_exit_tfm(struct crypto_akcipher *tfm) { struct rsa_key *pkey = akcipher_tfm_ctx(tfm); @@ -311,7 +324,9 @@ static struct akcipher_alg rsa = { .decrypt = rsa_dec, .sign = rsa_sign, .verify = rsa_verify, - .setkey = rsa_setkey, + .set_priv_key = rsa_set_priv_key, + .set_pub_key = rsa_set_pub_key, + .max_size = rsa_max_size, .exit = rsa_exit_tfm, .base = { .cra_name = "rsa", diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c index 8d96ce9..d226f48 100644 --- a/crypto/rsa_helper.c +++ b/crypto/rsa_helper.c @@ -15,7 +15,8 @@ #include <linux/err.h> #include <linux/fips.h> #include <crypto/internal/rsa.h> -#include "rsakey-asn1.h" +#include "rsapubkey-asn1.h" +#include "rsaprivkey-asn1.h" int rsa_get_n(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) @@ -94,8 +95,8 @@ void rsa_free_key(struct rsa_key *key) EXPORT_SYMBOL_GPL(rsa_free_key); /** - * rsa_parse_key() - extracts an rsa key from BER encoded buffer - * and stores it in the provided struct rsa_key + * rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer + * and stores it in the provided struct rsa_key * * @rsa_key: struct rsa_key key representation * @key: key in BER format @@ -103,13 +104,13 @@ EXPORT_SYMBOL_GPL(rsa_free_key); * * Return: 0 on success or error code in case of error */ -int rsa_parse_key(struct rsa_key *rsa_key, const void *key, - unsigned int key_len) +int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, + unsigned int key_len) { int ret; free_mpis(rsa_key); - ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len); + ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len); if (ret < 0) goto error; @@ -118,4 +119,31 @@ error: free_mpis(rsa_key); return ret; } -EXPORT_SYMBOL_GPL(rsa_parse_key); +EXPORT_SYMBOL_GPL(rsa_parse_pub_key); + +/** + * rsa_parse_pub_key() - extracts an rsa private key from BER encoded buffer + * and stores it in the provided struct rsa_key + * + * @rsa_key: struct rsa_key key representation + * @key: key in BER format + * @key_len: length of key + * + * Return: 0 on success or error code in case of error + */ +int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, + unsigned int key_len) +{ + int ret; + + free_mpis(rsa_key); + ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len); + if (ret < 0) + goto error; + + return 0; +error: + free_mpis(rsa_key); + return ret; +} +EXPORT_SYMBOL_GPL(rsa_parse_priv_key); diff --git a/crypto/rsakey.asn1 b/crypto/rsakey.asn1 deleted file mode 100644 index 3c7b5df..0000000 --- a/crypto/rsakey.asn1 +++ /dev/null @@ -1,5 +0,0 @@ -RsaKey ::= SEQUENCE { - n INTEGER ({ rsa_get_n }), - e INTEGER ({ rsa_get_e }), - d INTEGER ({ rsa_get_d }) -} diff --git a/crypto/rsaprivkey.asn1 b/crypto/rsaprivkey.asn1 new file mode 100644 index 0000000..731aea5 --- /dev/null +++ b/crypto/rsaprivkey.asn1 @@ -0,0 +1,11 @@ +RsaPrivKey ::= SEQUENCE { + version INTEGER, + n INTEGER ({ rsa_get_n }), + e INTEGER ({ rsa_get_e }), + d INTEGER ({ rsa_get_d }), + prime1 INTEGER, + prime2 INTEGER, + exponent1 INTEGER, + exponent2 INTEGER, + coefficient INTEGER +} diff --git a/crypto/rsapubkey.asn1 b/crypto/rsapubkey.asn1 new file mode 100644 index 0000000..725498e --- /dev/null +++ b/crypto/rsapubkey.asn1 @@ -0,0 +1,4 @@ +RsaPubKey ::= SEQUENCE { + n INTEGER ({ rsa_get_n }), + e INTEGER ({ rsa_get_e }) +} diff --git a/crypto/skcipher.c b/crypto/skcipher.c index dd5fc1b..7591928 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -91,7 +91,7 @@ static void crypto_exit_skcipher_ops_blkcipher(struct crypto_tfm *tfm) crypto_free_blkcipher(*ctx); } -int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm) +static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); @@ -182,7 +182,7 @@ static void crypto_exit_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) crypto_free_ablkcipher(*ctx); } -int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) +static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 2b00b61..46a4a75 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -48,6 +48,8 @@ #define ENCRYPT 1 #define DECRYPT 0 +#define MAX_DIGEST_SIZE 64 + /* * return a string with the driver name */ @@ -950,7 +952,7 @@ static void test_ahash_speed(const char *algo, unsigned int secs, struct tcrypt_result tresult; struct ahash_request *req; struct crypto_ahash *tfm; - static char output[1024]; + char *output; int i, ret; tfm = crypto_alloc_ahash(algo, 0, 0); @@ -963,9 +965,9 @@ static void test_ahash_speed(const char *algo, unsigned int secs, printk(KERN_INFO "\ntesting speed of async %s (%s)\n", algo, get_driver_name(crypto_ahash, tfm)); - if (crypto_ahash_digestsize(tfm) > sizeof(output)) { - pr_err("digestsize(%u) > outputbuffer(%zu)\n", - crypto_ahash_digestsize(tfm), sizeof(output)); + if (crypto_ahash_digestsize(tfm) > MAX_DIGEST_SIZE) { + pr_err("digestsize(%u) > %d\n", crypto_ahash_digestsize(tfm), + MAX_DIGEST_SIZE); goto out; } @@ -980,6 +982,10 @@ static void test_ahash_speed(const char *algo, unsigned int secs, ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, &tresult); + output = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL); + if (!output) + goto out_nomem; + for (i = 0; speed[i].blen != 0; i++) { if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { pr_err("template (%u) too big for tvmem (%lu)\n", @@ -1006,6 +1012,9 @@ static void test_ahash_speed(const char *algo, unsigned int secs, } } + kfree(output); + +out_nomem: ahash_request_free(req); out: diff --git a/crypto/testmgr.c b/crypto/testmgr.c index fa18753..ae8c57fd 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1034,12 +1034,22 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, q = data; if (memcmp(q, template[i].result, template[i].rlen)) { - pr_err("alg: skcipher%s: Test %d failed on %s for %s\n", + pr_err("alg: skcipher%s: Test %d failed (invalid result) on %s for %s\n", d, j, e, algo); hexdump(q, template[i].rlen); ret = -EINVAL; goto out; } + + if (template[i].iv_out && + memcmp(iv, template[i].iv_out, + crypto_skcipher_ivsize(tfm))) { + pr_err("alg: skcipher%s: Test %d failed (invalid output IV) on %s for %s\n", + d, j, e, algo); + hexdump(iv, crypto_skcipher_ivsize(tfm)); + ret = -EINVAL; + goto out; + } } j = 0; @@ -1845,34 +1855,34 @@ static int do_test_rsa(struct crypto_akcipher *tfm, struct tcrypt_result result; unsigned int out_len_max, out_len = 0; int err = -ENOMEM; + struct scatterlist src, dst, src_tab[2]; req = akcipher_request_alloc(tfm, GFP_KERNEL); if (!req) return err; init_completion(&result.completion); - err = crypto_akcipher_setkey(tfm, vecs->key, vecs->key_len); - if (err) - goto free_req; - akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size, - out_len); - /* expect this to fail, and update the required buf len */ - crypto_akcipher_encrypt(req); - out_len = req->dst_len; - if (!out_len) { - err = -EINVAL; + if (vecs->public_key_vec) + err = crypto_akcipher_set_pub_key(tfm, vecs->key, + vecs->key_len); + else + err = crypto_akcipher_set_priv_key(tfm, vecs->key, + vecs->key_len); + if (err) goto free_req; - } - out_len_max = out_len; - err = -ENOMEM; + out_len_max = crypto_akcipher_maxsize(tfm); outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); if (!outbuf_enc) goto free_req; - akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size, - out_len); + sg_init_table(src_tab, 2); + sg_set_buf(&src_tab[0], vecs->m, 8); + sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8); + sg_init_one(&dst, outbuf_enc, out_len_max); + akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size, + out_len_max); akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, &result); @@ -1882,13 +1892,13 @@ static int do_test_rsa(struct crypto_akcipher *tfm, pr_err("alg: rsa: encrypt test failed. err %d\n", err); goto free_all; } - if (out_len != vecs->c_size) { + if (req->dst_len != vecs->c_size) { pr_err("alg: rsa: encrypt test failed. Invalid output len\n"); err = -EINVAL; goto free_all; } /* verify that encrypted message is equal to expected */ - if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) { + if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) { pr_err("alg: rsa: encrypt test failed. Invalid output\n"); err = -EINVAL; goto free_all; @@ -1903,9 +1913,10 @@ static int do_test_rsa(struct crypto_akcipher *tfm, err = -ENOMEM; goto free_all; } + sg_init_one(&src, vecs->c, vecs->c_size); + sg_init_one(&dst, outbuf_dec, out_len_max); init_completion(&result.completion); - akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs->c_size, - out_len); + akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max); /* Run RSA decrypt - m = c^d mod n;*/ err = wait_async_op(&result, crypto_akcipher_decrypt(req)); @@ -2080,7 +2091,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(md5),ecb(cipher_null))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2096,7 +2106,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha1),cbc(aes))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2110,7 +2119,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha1),cbc(des))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2124,7 +2132,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha1),cbc(des3_ede))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2138,7 +2145,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha1),ecb(cipher_null))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2158,7 +2164,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha224),cbc(des))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2172,7 +2177,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha224),cbc(des3_ede))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2186,7 +2190,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha256),cbc(aes))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2200,7 +2203,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha256),cbc(des))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2214,7 +2216,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha256),cbc(des3_ede))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2228,7 +2229,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha384),cbc(des))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2242,7 +2242,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha384),cbc(des3_ede))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2256,7 +2255,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha512),cbc(aes))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2270,7 +2268,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha512),cbc(des))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2284,7 +2281,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha512),cbc(des3_ede))", .test = alg_test_aead, - .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -3011,7 +3007,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "ecb(des)", .test = alg_test_skcipher, - .fips_allowed = 1, .suite = { .cipher = { .enc = { @@ -3292,6 +3287,22 @@ static const struct alg_test_desc alg_test_descs[] = { .fips_allowed = 1, .test = alg_test_null, }, { + .alg = "kw(aes)", + .test = alg_test_skcipher, + .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { + .vecs = aes_kw_enc_tv_template, + .count = ARRAY_SIZE(aes_kw_enc_tv_template) + }, + .dec = { + .vecs = aes_kw_dec_tv_template, + .count = ARRAY_SIZE(aes_kw_dec_tv_template) + } + } + } + }, { .alg = "lrw(aes)", .test = alg_test_skcipher, .suite = { diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 64b8a80..da0a8fd 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -67,6 +67,7 @@ struct hash_testvec { struct cipher_testvec { char *key; char *iv; + char *iv_out; char *input; char *result; unsigned short tap[MAX_TAP]; @@ -149,7 +150,8 @@ static struct akcipher_testvec rsa_tv_template[] = { { #ifndef CONFIG_CRYPTO_FIPS .key = - "\x30\x81\x88" /* sequence of 136 bytes */ + "\x30\x81\x9A" /* sequence of 154 bytes */ + "\x02\x01\x01" /* version - integer of 1 byte */ "\x02\x41" /* modulus - integer of 65 bytes */ "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F" "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5" @@ -161,19 +163,25 @@ static struct akcipher_testvec rsa_tv_template[] = { "\x0A\x03\x37\x48\x62\x64\x87\x69\x5F\x5F\x30\xBC\x38\xB9\x8B\x44" "\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64" "\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9" - "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51", + "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51" + "\x02\x01\x00" /* prime1 - integer of 1 byte */ + "\x02\x01\x00" /* prime2 - integer of 1 byte */ + "\x02\x01\x00" /* exponent1 - integer of 1 byte */ + "\x02\x01\x00" /* exponent2 - integer of 1 byte */ + "\x02\x01\x00", /* coefficient - integer of 1 byte */ .m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a", .c = "\x63\x1c\xcd\x7b\xe1\x7e\xe4\xde\xc9\xa8\x89\xa1\x74\xcb\x3c\x63" "\x7d\x24\xec\x83\xc3\x15\xe4\x7f\x73\x05\x34\xd1\xec\x22\xbb\x8a" "\x5e\x32\x39\x6d\xc1\x1d\x7d\x50\x3b\x9f\x7a\xad\xf0\x2e\x25\x53" "\x9f\x6e\xbd\x4c\x55\x84\x0c\x9b\xcf\x1a\x4b\x51\x1e\x9e\x0c\x06", - .key_len = 139, + .key_len = 157, .m_size = 8, .c_size = 64, }, { .key = - "\x30\x82\x01\x0B" /* sequence of 267 bytes */ + "\x30\x82\x01\x1D" /* sequence of 285 bytes */ + "\x02\x01\x01" /* version - integer of 1 byte */ "\x02\x81\x81" /* modulus - integer of 129 bytes */ "\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71" "\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5" @@ -194,8 +202,13 @@ static struct akcipher_testvec rsa_tv_template[] = { "\x44\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A" "\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94" "\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3" - "\xC1", - .key_len = 271, + "\xC1" + "\x02\x01\x00" /* prime1 - integer of 1 byte */ + "\x02\x01\x00" /* prime2 - integer of 1 byte */ + "\x02\x01\x00" /* exponent1 - integer of 1 byte */ + "\x02\x01\x00" /* exponent2 - integer of 1 byte */ + "\x02\x01\x00", /* coefficient - integer of 1 byte */ + .key_len = 289, .m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a", .c = "\x74\x1b\x55\xac\x47\xb5\x08\x0a\x6e\x2b\x2d\xf7\x94\xb8\x8a\x95" @@ -211,7 +224,8 @@ static struct akcipher_testvec rsa_tv_template[] = { }, { #endif .key = - "\x30\x82\x02\x0D" /* sequence of 525 bytes */ + "\x30\x82\x02\x1F" /* sequence of 543 bytes */ + "\x02\x01\x01" /* version - integer of 1 byte */ "\x02\x82\x01\x00" /* modulus - integer of 256 bytes */ "\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D" "\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA" @@ -246,8 +260,13 @@ static struct akcipher_testvec rsa_tv_template[] = { "\x77\xAF\x51\x27\x5B\x5E\x69\xB8\x81\xE6\x11\xC5\x43\x23\x81\x04" "\x62\xFF\xE9\x46\xB8\xD8\x44\xDB\xA5\xCC\x31\x54\x34\xCE\x3E\x82" "\xD6\xBF\x7A\x0B\x64\x21\x6D\x88\x7E\x5B\x45\x12\x1E\x63\x8D\x49" - "\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71", - .key_len = 529, + "\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71" + "\x02\x01\x00" /* prime1 - integer of 1 byte */ + "\x02\x01\x00" /* prime2 - integer of 1 byte */ + "\x02\x01\x00" /* exponent1 - integer of 1 byte */ + "\x02\x01\x00" /* exponent2 - integer of 1 byte */ + "\x02\x01\x00", /* coefficient - integer of 1 byte */ + .key_len = 547, .m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a", .c = "\xb2\x97\x76\xb4\xae\x3e\x38\x3c\x7e\x64\x1f\xcc\xa2\x7f\xf6\xbe" @@ -23814,6 +23833,46 @@ static struct aead_testvec rfc7539esp_dec_tv_template[] = { }; /* + * All key wrapping test vectors taken from + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/kwtestvectors.zip + * + * Note: as documented in keywrap.c, the ivout for encryption is the first + * semiblock of the ciphertext from the test vector. For decryption, iv is + * the first semiblock of the ciphertext. + */ +static struct cipher_testvec aes_kw_enc_tv_template[] = { + { + .key = "\x75\x75\xda\x3a\x93\x60\x7c\xc2" + "\xbf\xd8\xce\xc7\xaa\xdf\xd9\xa6", + .klen = 16, + .input = "\x42\x13\x6d\x3c\x38\x4a\x3e\xea" + "\xc9\x5a\x06\x6f\xd2\x8f\xed\x3f", + .ilen = 16, + .result = "\xf6\x85\x94\x81\x6f\x64\xca\xa3" + "\xf5\x6f\xab\xea\x25\x48\xf5\xfb", + .rlen = 16, + .iv_out = "\x03\x1f\x6b\xd7\xe6\x1e\x64\x3d", + }, +}; + +static struct cipher_testvec aes_kw_dec_tv_template[] = { + { + .key = "\x80\xaa\x99\x73\x27\xa4\x80\x6b" + "\x6a\x7a\x41\xa5\x2b\x86\xc3\x71" + "\x03\x86\xf9\x32\x78\x6e\xf7\x96" + "\x76\xfa\xfb\x90\xb8\x26\x3c\x5f", + .klen = 32, + .input = "\xd3\x3d\x3d\x97\x7b\xf0\xa9\x15" + "\x59\xf9\x9c\x8a\xcd\x29\x3d\x43", + .ilen = 16, + .result = "\x0a\x25\x6b\xa7\x5c\xfa\x03\xaa" + "\xa0\x2b\xa9\x42\x03\xf1\x5b\xaa", + .rlen = 16, + .iv = "\x42\x3c\x96\x0d\x8a\x2a\xc4\xc1", + }, +}; + +/* * ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode) * test vectors, taken from Appendix B.2.9 and B.2.10: * http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf |