| .. | .. |
|---|
| 42 | 42 | * deprecated in 2.6 |
|---|
| 43 | 43 | */ |
|---|
| 44 | 44 | |
|---|
| 45 | +#include <crypto/arc4.h> |
|---|
| 45 | 46 | #include <crypto/hash.h> |
|---|
| 46 | | -#include <crypto/skcipher.h> |
|---|
| 47 | 47 | #include <linux/err.h> |
|---|
| 48 | +#include <linux/fips.h> |
|---|
| 48 | 49 | #include <linux/module.h> |
|---|
| 49 | 50 | #include <linux/kernel.h> |
|---|
| 50 | 51 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 63 | 64 | MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); |
|---|
| 64 | 65 | MODULE_LICENSE("Dual BSD/GPL"); |
|---|
| 65 | 66 | MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); |
|---|
| 66 | | -MODULE_SOFTDEP("pre: arc4"); |
|---|
| 67 | 67 | MODULE_VERSION("1.0.2"); |
|---|
| 68 | | - |
|---|
| 69 | | -static unsigned int |
|---|
| 70 | | -setup_sg(struct scatterlist *sg, const void *address, unsigned int length) |
|---|
| 71 | | -{ |
|---|
| 72 | | - sg_set_buf(sg, address, length); |
|---|
| 73 | | - return length; |
|---|
| 74 | | -} |
|---|
| 75 | 68 | |
|---|
| 76 | 69 | #define SHA1_PAD_SIZE 40 |
|---|
| 77 | 70 | |
|---|
| .. | .. |
|---|
| 96 | 89 | * State for an MPPE (de)compressor. |
|---|
| 97 | 90 | */ |
|---|
| 98 | 91 | struct ppp_mppe_state { |
|---|
| 99 | | - struct crypto_skcipher *arc4; |
|---|
| 92 | + struct arc4_ctx arc4; |
|---|
| 100 | 93 | struct shash_desc *sha1; |
|---|
| 101 | 94 | unsigned char *sha1_digest; |
|---|
| 102 | 95 | unsigned char master_key[MPPE_MAX_KEY_LEN]; |
|---|
| .. | .. |
|---|
| 155 | 148 | */ |
|---|
| 156 | 149 | static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) |
|---|
| 157 | 150 | { |
|---|
| 158 | | - struct scatterlist sg_in[1], sg_out[1]; |
|---|
| 159 | | - SKCIPHER_REQUEST_ON_STACK(req, state->arc4); |
|---|
| 160 | | - |
|---|
| 161 | | - skcipher_request_set_tfm(req, state->arc4); |
|---|
| 162 | | - skcipher_request_set_callback(req, 0, NULL, NULL); |
|---|
| 163 | | - |
|---|
| 164 | 151 | get_new_key_from_sha(state); |
|---|
| 165 | 152 | if (!initial_key) { |
|---|
| 166 | | - crypto_skcipher_setkey(state->arc4, state->sha1_digest, |
|---|
| 167 | | - state->keylen); |
|---|
| 168 | | - sg_init_table(sg_in, 1); |
|---|
| 169 | | - sg_init_table(sg_out, 1); |
|---|
| 170 | | - setup_sg(sg_in, state->sha1_digest, state->keylen); |
|---|
| 171 | | - setup_sg(sg_out, state->session_key, state->keylen); |
|---|
| 172 | | - skcipher_request_set_crypt(req, sg_in, sg_out, state->keylen, |
|---|
| 173 | | - NULL); |
|---|
| 174 | | - if (crypto_skcipher_encrypt(req)) |
|---|
| 175 | | - printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); |
|---|
| 153 | + arc4_setkey(&state->arc4, state->sha1_digest, state->keylen); |
|---|
| 154 | + arc4_crypt(&state->arc4, state->session_key, state->sha1_digest, |
|---|
| 155 | + state->keylen); |
|---|
| 176 | 156 | } else { |
|---|
| 177 | 157 | memcpy(state->session_key, state->sha1_digest, state->keylen); |
|---|
| 178 | 158 | } |
|---|
| .. | .. |
|---|
| 182 | 162 | state->session_key[1] = 0x26; |
|---|
| 183 | 163 | state->session_key[2] = 0x9e; |
|---|
| 184 | 164 | } |
|---|
| 185 | | - crypto_skcipher_setkey(state->arc4, state->session_key, state->keylen); |
|---|
| 186 | | - skcipher_request_zero(req); |
|---|
| 165 | + arc4_setkey(&state->arc4, state->session_key, state->keylen); |
|---|
| 187 | 166 | } |
|---|
| 188 | 167 | |
|---|
| 189 | 168 | /* |
|---|
| .. | .. |
|---|
| 196 | 175 | unsigned int digestsize; |
|---|
| 197 | 176 | |
|---|
| 198 | 177 | if (optlen != CILEN_MPPE + sizeof(state->master_key) || |
|---|
| 199 | | - options[0] != CI_MPPE || options[1] != CILEN_MPPE) |
|---|
| 178 | + options[0] != CI_MPPE || options[1] != CILEN_MPPE || |
|---|
| 179 | + fips_enabled) |
|---|
| 200 | 180 | goto out; |
|---|
| 201 | 181 | |
|---|
| 202 | 182 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
|---|
| 203 | 183 | if (state == NULL) |
|---|
| 204 | 184 | goto out; |
|---|
| 205 | 185 | |
|---|
| 206 | | - |
|---|
| 207 | | - state->arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
|---|
| 208 | | - if (IS_ERR(state->arc4)) { |
|---|
| 209 | | - state->arc4 = NULL; |
|---|
| 210 | | - goto out_free; |
|---|
| 211 | | - } |
|---|
| 212 | 186 | |
|---|
| 213 | 187 | shash = crypto_alloc_shash("sha1", 0, 0); |
|---|
| 214 | 188 | if (IS_ERR(shash)) |
|---|
| .. | .. |
|---|
| 222 | 196 | goto out_free; |
|---|
| 223 | 197 | } |
|---|
| 224 | 198 | state->sha1->tfm = shash; |
|---|
| 225 | | - state->sha1->flags = 0; |
|---|
| 226 | 199 | |
|---|
| 227 | 200 | digestsize = crypto_shash_digestsize(shash); |
|---|
| 228 | 201 | if (digestsize < MPPE_MAX_KEY_LEN) |
|---|
| .. | .. |
|---|
| 249 | 222 | kfree(state->sha1_digest); |
|---|
| 250 | 223 | if (state->sha1) { |
|---|
| 251 | 224 | crypto_free_shash(state->sha1->tfm); |
|---|
| 252 | | - kzfree(state->sha1); |
|---|
| 225 | + kfree_sensitive(state->sha1); |
|---|
| 253 | 226 | } |
|---|
| 254 | | - crypto_free_skcipher(state->arc4); |
|---|
| 255 | 227 | kfree(state); |
|---|
| 256 | 228 | out: |
|---|
| 257 | 229 | return NULL; |
|---|
| .. | .. |
|---|
| 266 | 238 | if (state) { |
|---|
| 267 | 239 | kfree(state->sha1_digest); |
|---|
| 268 | 240 | crypto_free_shash(state->sha1->tfm); |
|---|
| 269 | | - kzfree(state->sha1); |
|---|
| 270 | | - crypto_free_skcipher(state->arc4); |
|---|
| 271 | | - kfree(state); |
|---|
| 241 | + kfree_sensitive(state->sha1); |
|---|
| 242 | + kfree_sensitive(state); |
|---|
| 272 | 243 | } |
|---|
| 273 | 244 | } |
|---|
| 274 | 245 | |
|---|
| .. | .. |
|---|
| 367 | 338 | int isize, int osize) |
|---|
| 368 | 339 | { |
|---|
| 369 | 340 | struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
|---|
| 370 | | - SKCIPHER_REQUEST_ON_STACK(req, state->arc4); |
|---|
| 371 | 341 | int proto; |
|---|
| 372 | | - int err; |
|---|
| 373 | | - struct scatterlist sg_in[1], sg_out[1]; |
|---|
| 374 | 342 | |
|---|
| 375 | 343 | /* |
|---|
| 376 | 344 | * Check that the protocol is in the range we handle. |
|---|
| .. | .. |
|---|
| 421 | 389 | ibuf += 2; /* skip to proto field */ |
|---|
| 422 | 390 | isize -= 2; |
|---|
| 423 | 391 | |
|---|
| 424 | | - /* Encrypt packet */ |
|---|
| 425 | | - sg_init_table(sg_in, 1); |
|---|
| 426 | | - sg_init_table(sg_out, 1); |
|---|
| 427 | | - setup_sg(sg_in, ibuf, isize); |
|---|
| 428 | | - setup_sg(sg_out, obuf, osize); |
|---|
| 429 | | - |
|---|
| 430 | | - skcipher_request_set_tfm(req, state->arc4); |
|---|
| 431 | | - skcipher_request_set_callback(req, 0, NULL, NULL); |
|---|
| 432 | | - skcipher_request_set_crypt(req, sg_in, sg_out, isize, NULL); |
|---|
| 433 | | - err = crypto_skcipher_encrypt(req); |
|---|
| 434 | | - skcipher_request_zero(req); |
|---|
| 435 | | - if (err) { |
|---|
| 436 | | - printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); |
|---|
| 437 | | - return -1; |
|---|
| 438 | | - } |
|---|
| 392 | + arc4_crypt(&state->arc4, obuf, ibuf, isize); |
|---|
| 439 | 393 | |
|---|
| 440 | 394 | state->stats.unc_bytes += isize; |
|---|
| 441 | 395 | state->stats.unc_packets++; |
|---|
| .. | .. |
|---|
| 481 | 435 | int osize) |
|---|
| 482 | 436 | { |
|---|
| 483 | 437 | struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
|---|
| 484 | | - SKCIPHER_REQUEST_ON_STACK(req, state->arc4); |
|---|
| 485 | 438 | unsigned ccount; |
|---|
| 486 | 439 | int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; |
|---|
| 487 | | - struct scatterlist sg_in[1], sg_out[1]; |
|---|
| 488 | 440 | |
|---|
| 489 | 441 | if (isize <= PPP_HDRLEN + MPPE_OVHD) { |
|---|
| 490 | 442 | if (state->debug) |
|---|
| .. | .. |
|---|
| 611 | 563 | * Decrypt the first byte in order to check if it is |
|---|
| 612 | 564 | * a compressed or uncompressed protocol field. |
|---|
| 613 | 565 | */ |
|---|
| 614 | | - sg_init_table(sg_in, 1); |
|---|
| 615 | | - sg_init_table(sg_out, 1); |
|---|
| 616 | | - setup_sg(sg_in, ibuf, 1); |
|---|
| 617 | | - setup_sg(sg_out, obuf, 1); |
|---|
| 618 | | - |
|---|
| 619 | | - skcipher_request_set_tfm(req, state->arc4); |
|---|
| 620 | | - skcipher_request_set_callback(req, 0, NULL, NULL); |
|---|
| 621 | | - skcipher_request_set_crypt(req, sg_in, sg_out, 1, NULL); |
|---|
| 622 | | - if (crypto_skcipher_decrypt(req)) { |
|---|
| 623 | | - printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); |
|---|
| 624 | | - osize = DECOMP_ERROR; |
|---|
| 625 | | - goto out_zap_req; |
|---|
| 626 | | - } |
|---|
| 566 | + arc4_crypt(&state->arc4, obuf, ibuf, 1); |
|---|
| 627 | 567 | |
|---|
| 628 | 568 | /* |
|---|
| 629 | 569 | * Do PFC decompression. |
|---|
| .. | .. |
|---|
| 638 | 578 | } |
|---|
| 639 | 579 | |
|---|
| 640 | 580 | /* And finally, decrypt the rest of the packet. */ |
|---|
| 641 | | - setup_sg(sg_in, ibuf + 1, isize - 1); |
|---|
| 642 | | - setup_sg(sg_out, obuf + 1, osize - 1); |
|---|
| 643 | | - skcipher_request_set_crypt(req, sg_in, sg_out, isize - 1, NULL); |
|---|
| 644 | | - if (crypto_skcipher_decrypt(req)) { |
|---|
| 645 | | - printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); |
|---|
| 646 | | - osize = DECOMP_ERROR; |
|---|
| 647 | | - goto out_zap_req; |
|---|
| 648 | | - } |
|---|
| 581 | + arc4_crypt(&state->arc4, obuf + 1, ibuf + 1, isize - 1); |
|---|
| 649 | 582 | |
|---|
| 650 | 583 | state->stats.unc_bytes += osize; |
|---|
| 651 | 584 | state->stats.unc_packets++; |
|---|
| .. | .. |
|---|
| 655 | 588 | /* good packet credit */ |
|---|
| 656 | 589 | state->sanity_errors >>= 1; |
|---|
| 657 | 590 | |
|---|
| 658 | | -out_zap_req: |
|---|
| 659 | | - skcipher_request_zero(req); |
|---|
| 660 | 591 | return osize; |
|---|
| 661 | 592 | |
|---|
| 662 | 593 | sanity_error: |
|---|
| .. | .. |
|---|
| 729 | 660 | static int __init ppp_mppe_init(void) |
|---|
| 730 | 661 | { |
|---|
| 731 | 662 | int answer; |
|---|
| 732 | | - if (!(crypto_has_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && |
|---|
| 733 | | - crypto_has_ahash("sha1", 0, CRYPTO_ALG_ASYNC))) |
|---|
| 663 | + if (fips_enabled || !crypto_has_ahash("sha1", 0, CRYPTO_ALG_ASYNC)) |
|---|
| 734 | 664 | return -ENODEV; |
|---|
| 735 | 665 | |
|---|
| 736 | 666 | sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); |
|---|