diff options
| author | Kevin Coffman <kwc@citi.umich.edu> | 2010-03-17 13:03:06 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:20 -0400 |
| commit | fffdaef2eb4a7333952e55cf97f1fc0fcc35f981 (patch) | |
| tree | bd4e4b39ec901feb27b91d33d4f52e723f3584d7 | |
| parent | 5af46547ec451918f3ba51efe59b317d33adf701 (diff) | |
gss_krb5: Add support for rc4-hmac encryption
Add necessary changes to add kernel support for the rc4-hmac Kerberos
encryption type used by Microsoft and described in rfc4757.
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | include/linux/sunrpc/gss_krb5.h | 9 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_crypto.c | 255 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 96 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_seal.c | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_seqnum.c | 77 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_unseal.c | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 66 |
7 files changed, 492 insertions, 13 deletions
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 79f6ac2492f5..5e774a5abf2c 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h | |||
| @@ -317,5 +317,14 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, | |||
| 317 | struct xdr_buf *buf, u32 *plainoffset, | 317 | struct xdr_buf *buf, u32 *plainoffset, |
| 318 | u32 *plainlen); | 318 | u32 *plainlen); |
| 319 | 319 | ||
| 320 | int | ||
| 321 | krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, | ||
| 322 | struct crypto_blkcipher *cipher, | ||
| 323 | unsigned char *cksum); | ||
| 324 | |||
| 325 | int | ||
| 326 | krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, | ||
| 327 | struct crypto_blkcipher *cipher, | ||
| 328 | s32 seqnum); | ||
| 320 | void | 329 | void |
| 321 | gss_krb5_make_confounder(char *p, u32 conflen); | 330 | gss_krb5_make_confounder(char *p, u32 conflen); |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index ed4106a3daf2..75ee993ea057 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
| @@ -124,6 +124,114 @@ checksummer(struct scatterlist *sg, void *data) | |||
| 124 | return crypto_hash_update(desc, sg, sg->length); | 124 | return crypto_hash_update(desc, sg, sg->length); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int | ||
| 128 | arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4]) | ||
| 129 | { | ||
| 130 | unsigned int ms_usage; | ||
| 131 | |||
| 132 | switch (usage) { | ||
| 133 | case KG_USAGE_SIGN: | ||
| 134 | ms_usage = 15; | ||
| 135 | break; | ||
| 136 | case KG_USAGE_SEAL: | ||
| 137 | ms_usage = 13; | ||
| 138 | break; | ||
| 139 | default: | ||
| 140 | return EINVAL;; | ||
| 141 | } | ||
| 142 | salt[0] = (ms_usage >> 0) & 0xff; | ||
| 143 | salt[1] = (ms_usage >> 8) & 0xff; | ||
| 144 | salt[2] = (ms_usage >> 16) & 0xff; | ||
| 145 | salt[3] = (ms_usage >> 24) & 0xff; | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static u32 | ||
| 151 | make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, | ||
| 152 | struct xdr_buf *body, int body_offset, u8 *cksumkey, | ||
| 153 | unsigned int usage, struct xdr_netobj *cksumout) | ||
| 154 | { | ||
| 155 | struct hash_desc desc; | ||
| 156 | struct scatterlist sg[1]; | ||
| 157 | int err; | ||
| 158 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | ||
| 159 | u8 rc4salt[4]; | ||
| 160 | struct crypto_hash *md5; | ||
| 161 | struct crypto_hash *hmac_md5; | ||
| 162 | |||
| 163 | if (cksumkey == NULL) | ||
| 164 | return GSS_S_FAILURE; | ||
| 165 | |||
| 166 | if (cksumout->len < kctx->gk5e->cksumlength) { | ||
| 167 | dprintk("%s: checksum buffer length, %u, too small for %s\n", | ||
| 168 | __func__, cksumout->len, kctx->gk5e->name); | ||
| 169 | return GSS_S_FAILURE; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (arcfour_hmac_md5_usage_to_salt(usage, rc4salt)) { | ||
| 173 | dprintk("%s: invalid usage value %u\n", __func__, usage); | ||
| 174 | return GSS_S_FAILURE; | ||
| 175 | } | ||
| 176 | |||
| 177 | md5 = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); | ||
| 178 | if (IS_ERR(md5)) | ||
| 179 | return GSS_S_FAILURE; | ||
| 180 | |||
| 181 | hmac_md5 = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, | ||
| 182 | CRYPTO_ALG_ASYNC); | ||
| 183 | if (IS_ERR(hmac_md5)) { | ||
| 184 | crypto_free_hash(md5); | ||
| 185 | return GSS_S_FAILURE; | ||
| 186 | } | ||
| 187 | |||
| 188 | desc.tfm = md5; | ||
| 189 | desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 190 | |||
| 191 | err = crypto_hash_init(&desc); | ||
| 192 | if (err) | ||
| 193 | goto out; | ||
| 194 | sg_init_one(sg, rc4salt, 4); | ||
| 195 | err = crypto_hash_update(&desc, sg, 4); | ||
| 196 | if (err) | ||
| 197 | goto out; | ||
| 198 | |||
| 199 | sg_init_one(sg, header, hdrlen); | ||
| 200 | err = crypto_hash_update(&desc, sg, hdrlen); | ||
| 201 | if (err) | ||
| 202 | goto out; | ||
| 203 | err = xdr_process_buf(body, body_offset, body->len - body_offset, | ||
| 204 | checksummer, &desc); | ||
| 205 | if (err) | ||
| 206 | goto out; | ||
| 207 | err = crypto_hash_final(&desc, checksumdata); | ||
| 208 | if (err) | ||
| 209 | goto out; | ||
| 210 | |||
| 211 | desc.tfm = hmac_md5; | ||
| 212 | desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 213 | |||
| 214 | err = crypto_hash_init(&desc); | ||
| 215 | if (err) | ||
| 216 | goto out; | ||
| 217 | err = crypto_hash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength); | ||
| 218 | if (err) | ||
| 219 | goto out; | ||
| 220 | |||
| 221 | sg_init_one(sg, checksumdata, crypto_hash_digestsize(md5)); | ||
| 222 | err = crypto_hash_digest(&desc, sg, crypto_hash_digestsize(md5), | ||
| 223 | checksumdata); | ||
| 224 | if (err) | ||
| 225 | goto out; | ||
| 226 | |||
| 227 | memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength); | ||
| 228 | cksumout->len = kctx->gk5e->cksumlength; | ||
| 229 | out: | ||
| 230 | crypto_free_hash(md5); | ||
| 231 | crypto_free_hash(hmac_md5); | ||
| 232 | return err ? GSS_S_FAILURE : 0; | ||
| 233 | } | ||
| 234 | |||
| 127 | /* | 235 | /* |
| 128 | * checksum the plaintext data and hdrlen bytes of the token header | 236 | * checksum the plaintext data and hdrlen bytes of the token header |
| 129 | * The checksum is performed over the first 8 bytes of the | 237 | * The checksum is performed over the first 8 bytes of the |
| @@ -140,6 +248,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, | |||
| 140 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; | 248 | u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
| 141 | unsigned int checksumlen; | 249 | unsigned int checksumlen; |
| 142 | 250 | ||
| 251 | if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) | ||
| 252 | return make_checksum_hmac_md5(kctx, header, hdrlen, | ||
| 253 | body, body_offset, | ||
| 254 | cksumkey, usage, cksumout); | ||
| 255 | |||
| 143 | if (cksumout->len < kctx->gk5e->cksumlength) { | 256 | if (cksumout->len < kctx->gk5e->cksumlength) { |
| 144 | dprintk("%s: checksum buffer length, %u, too small for %s\n", | 257 | dprintk("%s: checksum buffer length, %u, too small for %s\n", |
| 145 | __func__, cksumout->len, kctx->gk5e->name); | 258 | __func__, cksumout->len, kctx->gk5e->name); |
| @@ -733,3 +846,145 @@ out_err: | |||
| 733 | ret = GSS_S_FAILURE; | 846 | ret = GSS_S_FAILURE; |
| 734 | return ret; | 847 | return ret; |
| 735 | } | 848 | } |
| 849 | |||
| 850 | /* | ||
| 851 | * Compute Kseq given the initial session key and the checksum. | ||
| 852 | * Set the key of the given cipher. | ||
| 853 | */ | ||
| 854 | int | ||
| 855 | krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, | ||
| 856 | unsigned char *cksum) | ||
| 857 | { | ||
| 858 | struct crypto_hash *hmac; | ||
| 859 | struct hash_desc desc; | ||
| 860 | struct scatterlist sg[1]; | ||
| 861 | u8 Kseq[GSS_KRB5_MAX_KEYLEN]; | ||
| 862 | u32 zeroconstant = 0; | ||
| 863 | int err; | ||
| 864 | |||
| 865 | dprintk("%s: entered\n", __func__); | ||
| 866 | |||
| 867 | hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); | ||
| 868 | if (IS_ERR(hmac)) { | ||
| 869 | dprintk("%s: error %ld, allocating hash '%s'\n", | ||
| 870 | __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); | ||
| 871 | return PTR_ERR(hmac); | ||
| 872 | } | ||
| 873 | |||
| 874 | desc.tfm = hmac; | ||
| 875 | desc.flags = 0; | ||
| 876 | |||
| 877 | err = crypto_hash_init(&desc); | ||
| 878 | if (err) | ||
| 879 | goto out_err; | ||
| 880 | |||
| 881 | /* Compute intermediate Kseq from session key */ | ||
| 882 | err = crypto_hash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength); | ||
| 883 | if (err) | ||
| 884 | goto out_err; | ||
| 885 | |||
| 886 | sg_init_table(sg, 1); | ||
| 887 | sg_set_buf(sg, &zeroconstant, 4); | ||
| 888 | |||
| 889 | err = crypto_hash_digest(&desc, sg, 4, Kseq); | ||
| 890 | if (err) | ||
| 891 | goto out_err; | ||
| 892 | |||
| 893 | /* Compute final Kseq from the checksum and intermediate Kseq */ | ||
| 894 | err = crypto_hash_setkey(hmac, Kseq, kctx->gk5e->keylength); | ||
| 895 | if (err) | ||
| 896 | goto out_err; | ||
| 897 | |||
| 898 | sg_set_buf(sg, cksum, 8); | ||
| 899 | |||
| 900 | err = crypto_hash_digest(&desc, sg, 8, Kseq); | ||
| 901 | if (err) | ||
| 902 | goto out_err; | ||
| 903 | |||
| 904 | err = crypto_blkcipher_setkey(cipher, Kseq, kctx->gk5e->keylength); | ||
| 905 | if (err) | ||
| 906 | goto out_err; | ||
| 907 | |||
| 908 | err = 0; | ||
| 909 | |||
| 910 | out_err: | ||
| 911 | crypto_free_hash(hmac); | ||
| 912 | dprintk("%s: returning %d\n", __func__, err); | ||
| 913 | return err; | ||
| 914 | } | ||
| 915 | |||
| 916 | /* | ||
| 917 | * Compute Kcrypt given the initial session key and the plaintext seqnum. | ||
| 918 | * Set the key of cipher kctx->enc. | ||
| 919 | */ | ||
| 920 | int | ||
| 921 | krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, | ||
| 922 | s32 seqnum) | ||
| 923 | { | ||
| 924 | struct crypto_hash *hmac; | ||
| 925 | struct hash_desc desc; | ||
| 926 | struct scatterlist sg[1]; | ||
| 927 | u8 Kcrypt[GSS_KRB5_MAX_KEYLEN]; | ||
| 928 | u8 zeroconstant[4] = {0}; | ||
| 929 | u8 seqnumarray[4]; | ||
| 930 | int err, i; | ||
| 931 | |||
| 932 | dprintk("%s: entered, seqnum %u\n", __func__, seqnum); | ||
| 933 | |||
| 934 | hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); | ||
| 935 | if (IS_ERR(hmac)) { | ||
| 936 | dprintk("%s: error %ld, allocating hash '%s'\n", | ||
| 937 | __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); | ||
| 938 | return PTR_ERR(hmac); | ||
| 939 | } | ||
| 940 | |||
| 941 | desc.tfm = hmac; | ||
| 942 | desc.flags = 0; | ||
| 943 | |||
| 944 | err = crypto_hash_init(&desc); | ||
| 945 | if (err) | ||
| 946 | goto out_err; | ||
| 947 | |||
| 948 | /* Compute intermediate Kcrypt from session key */ | ||
| 949 | for (i = 0; i < kctx->gk5e->keylength; i++) | ||
| 950 | Kcrypt[i] = kctx->Ksess[i] ^ 0xf0; | ||
| 951 | |||
| 952 | err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); | ||
| 953 | if (err) | ||
| 954 | goto out_err; | ||
| 955 | |||
| 956 | sg_init_table(sg, 1); | ||
| 957 | sg_set_buf(sg, zeroconstant, 4); | ||
| 958 | |||
| 959 | err = crypto_hash_digest(&desc, sg, 4, Kcrypt); | ||
| 960 | if (err) | ||
| 961 | goto out_err; | ||
| 962 | |||
| 963 | /* Compute final Kcrypt from the seqnum and intermediate Kcrypt */ | ||
| 964 | err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); | ||
| 965 | if (err) | ||
| 966 | goto out_err; | ||
| 967 | |||
| 968 | seqnumarray[0] = (unsigned char) ((seqnum >> 24) & 0xff); | ||
| 969 | seqnumarray[1] = (unsigned char) ((seqnum >> 16) & 0xff); | ||
| 970 | seqnumarray[2] = (unsigned char) ((seqnum >> 8) & 0xff); | ||
| 971 | seqnumarray[3] = (unsigned char) ((seqnum >> 0) & 0xff); | ||
| 972 | |||
| 973 | sg_set_buf(sg, seqnumarray, 4); | ||
| 974 | |||
| 975 | err = crypto_hash_digest(&desc, sg, 4, Kcrypt); | ||
| 976 | if (err) | ||
| 977 | goto out_err; | ||
| 978 | |||
| 979 | err = crypto_blkcipher_setkey(cipher, Kcrypt, kctx->gk5e->keylength); | ||
| 980 | if (err) | ||
| 981 | goto out_err; | ||
| 982 | |||
| 983 | err = 0; | ||
| 984 | |||
| 985 | out_err: | ||
| 986 | crypto_free_hash(hmac); | ||
| 987 | dprintk("%s: returning %d\n", __func__, err); | ||
| 988 | return err; | ||
| 989 | } | ||
| 990 | |||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index ef6b31349046..54eda5f0c58b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
| @@ -73,6 +73,27 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { | |||
| 73 | .keyed_cksum = 0, | 73 | .keyed_cksum = 0, |
| 74 | }, | 74 | }, |
| 75 | /* | 75 | /* |
| 76 | * RC4-HMAC | ||
| 77 | */ | ||
| 78 | { | ||
| 79 | .etype = ENCTYPE_ARCFOUR_HMAC, | ||
| 80 | .ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR, | ||
| 81 | .name = "rc4-hmac", | ||
| 82 | .encrypt_name = "ecb(arc4)", | ||
| 83 | .cksum_name = "hmac(md5)", | ||
| 84 | .encrypt = krb5_encrypt, | ||
| 85 | .decrypt = krb5_decrypt, | ||
| 86 | .mk_key = NULL, | ||
| 87 | .signalg = SGN_ALG_HMAC_MD5, | ||
| 88 | .sealalg = SEAL_ALG_MICROSOFT_RC4, | ||
| 89 | .keybytes = 16, | ||
| 90 | .keylength = 16, | ||
| 91 | .blocksize = 1, | ||
| 92 | .conflen = 8, | ||
| 93 | .cksumlength = 8, | ||
| 94 | .keyed_cksum = 1, | ||
| 95 | }, | ||
| 96 | /* | ||
| 76 | * 3DES | 97 | * 3DES |
| 77 | */ | 98 | */ |
| 78 | { | 99 | { |
| @@ -392,6 +413,79 @@ out_err: | |||
| 392 | return -EINVAL; | 413 | return -EINVAL; |
| 393 | } | 414 | } |
| 394 | 415 | ||
| 416 | /* | ||
| 417 | * Note that RC4 depends on deriving keys using the sequence | ||
| 418 | * number or the checksum of a token. Therefore, the final keys | ||
| 419 | * cannot be calculated until the token is being constructed! | ||
| 420 | */ | ||
| 421 | static int | ||
| 422 | context_derive_keys_rc4(struct krb5_ctx *ctx) | ||
| 423 | { | ||
| 424 | struct crypto_hash *hmac; | ||
| 425 | char sigkeyconstant[] = "signaturekey"; | ||
| 426 | int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ | ||
| 427 | struct hash_desc desc; | ||
| 428 | struct scatterlist sg[1]; | ||
| 429 | int err; | ||
| 430 | |||
| 431 | dprintk("RPC: %s: entered\n", __func__); | ||
| 432 | /* | ||
| 433 | * derive cksum (aka Ksign) key | ||
| 434 | */ | ||
| 435 | hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); | ||
| 436 | if (IS_ERR(hmac)) { | ||
| 437 | dprintk("%s: error %ld allocating hash '%s'\n", | ||
| 438 | __func__, PTR_ERR(hmac), ctx->gk5e->cksum_name); | ||
| 439 | err = PTR_ERR(hmac); | ||
| 440 | goto out_err; | ||
| 441 | } | ||
| 442 | |||
| 443 | err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength); | ||
| 444 | if (err) | ||
| 445 | goto out_err_free_hmac; | ||
| 446 | |||
| 447 | sg_init_table(sg, 1); | ||
| 448 | sg_set_buf(sg, sigkeyconstant, slen); | ||
| 449 | |||
| 450 | desc.tfm = hmac; | ||
| 451 | desc.flags = 0; | ||
| 452 | |||
| 453 | err = crypto_hash_init(&desc); | ||
| 454 | if (err) | ||
| 455 | goto out_err_free_hmac; | ||
| 456 | |||
| 457 | err = crypto_hash_digest(&desc, sg, slen, ctx->cksum); | ||
| 458 | if (err) | ||
| 459 | goto out_err_free_hmac; | ||
| 460 | /* | ||
| 461 | * allocate hash, and blkciphers for data and seqnum encryption | ||
| 462 | */ | ||
| 463 | ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, | ||
| 464 | CRYPTO_ALG_ASYNC); | ||
| 465 | if (IS_ERR(ctx->enc)) { | ||
| 466 | err = PTR_ERR(ctx->enc); | ||
| 467 | goto out_err_free_hmac; | ||
| 468 | } | ||
| 469 | |||
| 470 | ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, | ||
| 471 | CRYPTO_ALG_ASYNC); | ||
| 472 | if (IS_ERR(ctx->seq)) { | ||
| 473 | crypto_free_blkcipher(ctx->enc); | ||
| 474 | err = PTR_ERR(ctx->seq); | ||
| 475 | goto out_err_free_hmac; | ||
| 476 | } | ||
| 477 | |||
| 478 | dprintk("RPC: %s: returning success\n", __func__); | ||
| 479 | |||
| 480 | err = 0; | ||
| 481 | |||
| 482 | out_err_free_hmac: | ||
| 483 | crypto_free_hash(hmac); | ||
| 484 | out_err: | ||
| 485 | dprintk("RPC: %s: returning %d\n", __func__, err); | ||
| 486 | return err; | ||
| 487 | } | ||
| 488 | |||
| 395 | static int | 489 | static int |
| 396 | context_derive_keys_new(struct krb5_ctx *ctx) | 490 | context_derive_keys_new(struct krb5_ctx *ctx) |
| 397 | { | 491 | { |
| @@ -561,6 +655,8 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
| 561 | switch (ctx->enctype) { | 655 | switch (ctx->enctype) { |
| 562 | case ENCTYPE_DES3_CBC_RAW: | 656 | case ENCTYPE_DES3_CBC_RAW: |
| 563 | return context_derive_keys_des3(ctx); | 657 | return context_derive_keys_des3(ctx); |
| 658 | case ENCTYPE_ARCFOUR_HMAC: | ||
| 659 | return context_derive_keys_rc4(ctx); | ||
| 564 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 660 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
| 565 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 661 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
| 566 | return context_derive_keys_new(ctx); | 662 | return context_derive_keys_new(ctx); |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 36fe487d93d2..d7941eab7796 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c | |||
| @@ -213,6 +213,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, | |||
| 213 | BUG(); | 213 | BUG(); |
| 214 | case ENCTYPE_DES_CBC_RAW: | 214 | case ENCTYPE_DES_CBC_RAW: |
| 215 | case ENCTYPE_DES3_CBC_RAW: | 215 | case ENCTYPE_DES3_CBC_RAW: |
| 216 | case ENCTYPE_ARCFOUR_HMAC: | ||
| 216 | return gss_get_mic_v1(ctx, text, token); | 217 | return gss_get_mic_v1(ctx, text, token); |
| 217 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 218 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
| 218 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 219 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c index 83b593084976..415c013ba382 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c | |||
| @@ -39,6 +39,38 @@ | |||
| 39 | # define RPCDBG_FACILITY RPCDBG_AUTH | 39 | # define RPCDBG_FACILITY RPCDBG_AUTH |
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | static s32 | ||
| 43 | krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum, | ||
| 44 | unsigned char *cksum, unsigned char *buf) | ||
| 45 | { | ||
| 46 | struct crypto_blkcipher *cipher; | ||
| 47 | unsigned char plain[8]; | ||
| 48 | s32 code; | ||
| 49 | |||
| 50 | dprintk("RPC: %s:\n", __func__); | ||
| 51 | cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, | ||
| 52 | CRYPTO_ALG_ASYNC); | ||
| 53 | if (IS_ERR(cipher)) | ||
| 54 | return PTR_ERR(cipher); | ||
| 55 | |||
| 56 | plain[0] = (unsigned char) ((seqnum >> 24) & 0xff); | ||
| 57 | plain[1] = (unsigned char) ((seqnum >> 16) & 0xff); | ||
| 58 | plain[2] = (unsigned char) ((seqnum >> 8) & 0xff); | ||
| 59 | plain[3] = (unsigned char) ((seqnum >> 0) & 0xff); | ||
| 60 | plain[4] = direction; | ||
| 61 | plain[5] = direction; | ||
| 62 | plain[6] = direction; | ||
| 63 | plain[7] = direction; | ||
| 64 | |||
| 65 | code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); | ||
| 66 | if (code) | ||
| 67 | goto out; | ||
| 68 | |||
| 69 | code = krb5_encrypt(cipher, cksum, plain, buf, 8); | ||
| 70 | out: | ||
| 71 | crypto_free_blkcipher(cipher); | ||
| 72 | return code; | ||
| 73 | } | ||
| 42 | s32 | 74 | s32 |
| 43 | krb5_make_seq_num(struct krb5_ctx *kctx, | 75 | krb5_make_seq_num(struct krb5_ctx *kctx, |
| 44 | struct crypto_blkcipher *key, | 76 | struct crypto_blkcipher *key, |
| @@ -48,6 +80,10 @@ krb5_make_seq_num(struct krb5_ctx *kctx, | |||
| 48 | { | 80 | { |
| 49 | unsigned char plain[8]; | 81 | unsigned char plain[8]; |
| 50 | 82 | ||
| 83 | if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) | ||
| 84 | return krb5_make_rc4_seq_num(kctx, direction, seqnum, | ||
| 85 | cksum, buf); | ||
| 86 | |||
| 51 | plain[0] = (unsigned char) (seqnum & 0xff); | 87 | plain[0] = (unsigned char) (seqnum & 0xff); |
| 52 | plain[1] = (unsigned char) ((seqnum >> 8) & 0xff); | 88 | plain[1] = (unsigned char) ((seqnum >> 8) & 0xff); |
| 53 | plain[2] = (unsigned char) ((seqnum >> 16) & 0xff); | 89 | plain[2] = (unsigned char) ((seqnum >> 16) & 0xff); |
| @@ -61,6 +97,43 @@ krb5_make_seq_num(struct krb5_ctx *kctx, | |||
| 61 | return krb5_encrypt(key, cksum, plain, buf, 8); | 97 | return krb5_encrypt(key, cksum, plain, buf, 8); |
| 62 | } | 98 | } |
| 63 | 99 | ||
| 100 | static s32 | ||
| 101 | krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, | ||
| 102 | unsigned char *buf, int *direction, s32 *seqnum) | ||
| 103 | { | ||
| 104 | struct crypto_blkcipher *cipher; | ||
| 105 | unsigned char plain[8]; | ||
| 106 | s32 code; | ||
| 107 | |||
| 108 | dprintk("RPC: %s:\n", __func__); | ||
| 109 | cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, | ||
| 110 | CRYPTO_ALG_ASYNC); | ||
| 111 | if (IS_ERR(cipher)) | ||
| 112 | return PTR_ERR(cipher); | ||
| 113 | |||
| 114 | code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); | ||
| 115 | if (code) | ||
| 116 | goto out; | ||
| 117 | |||
| 118 | code = krb5_decrypt(cipher, cksum, buf, plain, 8); | ||
| 119 | if (code) | ||
| 120 | goto out; | ||
| 121 | |||
| 122 | if ((plain[4] != plain[5]) || (plain[4] != plain[6]) | ||
| 123 | || (plain[4] != plain[7])) { | ||
| 124 | code = (s32)KG_BAD_SEQ; | ||
| 125 | goto out; | ||
| 126 | } | ||
| 127 | |||
| 128 | *direction = plain[4]; | ||
| 129 | |||
| 130 | *seqnum = ((plain[0] << 24) | (plain[1] << 16) | | ||
| 131 | (plain[2] << 8) | (plain[3])); | ||
| 132 | out: | ||
| 133 | crypto_free_blkcipher(cipher); | ||
| 134 | return code; | ||
| 135 | } | ||
| 136 | |||
| 64 | s32 | 137 | s32 |
| 65 | krb5_get_seq_num(struct krb5_ctx *kctx, | 138 | krb5_get_seq_num(struct krb5_ctx *kctx, |
| 66 | unsigned char *cksum, | 139 | unsigned char *cksum, |
| @@ -73,6 +146,10 @@ krb5_get_seq_num(struct krb5_ctx *kctx, | |||
| 73 | 146 | ||
| 74 | dprintk("RPC: krb5_get_seq_num:\n"); | 147 | dprintk("RPC: krb5_get_seq_num:\n"); |
| 75 | 148 | ||
| 149 | if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) | ||
| 150 | return krb5_get_rc4_seq_num(kctx, cksum, buf, | ||
| 151 | direction, seqnum); | ||
| 152 | |||
| 76 | if ((code = krb5_decrypt(key, cksum, buf, plain, 8))) | 153 | if ((code = krb5_decrypt(key, cksum, buf, plain, 8))) |
| 77 | return code; | 154 | return code; |
| 78 | 155 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 97eb91b8c70c..6cd930f3678f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c | |||
| @@ -216,6 +216,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, | |||
| 216 | BUG(); | 216 | BUG(); |
| 217 | case ENCTYPE_DES_CBC_RAW: | 217 | case ENCTYPE_DES_CBC_RAW: |
| 218 | case ENCTYPE_DES3_CBC_RAW: | 218 | case ENCTYPE_DES3_CBC_RAW: |
| 219 | case ENCTYPE_ARCFOUR_HMAC: | ||
| 219 | return gss_verify_mic_v1(ctx, message_buffer, read_token); | 220 | return gss_verify_mic_v1(ctx, message_buffer, read_token); |
| 220 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 221 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
| 221 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 222 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 383db891c835..2763e3e48db4 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
| @@ -232,9 +232,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | |||
| 232 | seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))) | 232 | seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))) |
| 233 | return GSS_S_FAILURE; | 233 | return GSS_S_FAILURE; |
| 234 | 234 | ||
| 235 | if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - conflen, | 235 | if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { |
| 236 | pages)) | 236 | struct crypto_blkcipher *cipher; |
| 237 | return GSS_S_FAILURE; | 237 | int err; |
| 238 | cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, | ||
| 239 | CRYPTO_ALG_ASYNC); | ||
| 240 | if (IS_ERR(cipher)) | ||
| 241 | return GSS_S_FAILURE; | ||
| 242 | |||
| 243 | krb5_rc4_setup_enc_key(kctx, cipher, seq_send); | ||
| 244 | |||
| 245 | err = gss_encrypt_xdr_buf(cipher, buf, | ||
| 246 | offset + headlen - conflen, pages); | ||
| 247 | crypto_free_blkcipher(cipher); | ||
| 248 | if (err) | ||
| 249 | return GSS_S_FAILURE; | ||
| 250 | } else { | ||
| 251 | if (gss_encrypt_xdr_buf(kctx->enc, buf, | ||
| 252 | offset + headlen - conflen, pages)) | ||
| 253 | return GSS_S_FAILURE; | ||
| 254 | } | ||
| 238 | 255 | ||
| 239 | return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; | 256 | return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; |
| 240 | } | 257 | } |
| @@ -291,8 +308,37 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
| 291 | */ | 308 | */ |
| 292 | crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) - | 309 | crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) - |
| 293 | (unsigned char *)buf->head[0].iov_base; | 310 | (unsigned char *)buf->head[0].iov_base; |
| 294 | if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) | 311 | |
| 295 | return GSS_S_DEFECTIVE_TOKEN; | 312 | /* |
| 313 | * Need plaintext seqnum to derive encryption key for arcfour-hmac | ||
| 314 | */ | ||
| 315 | if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, | ||
| 316 | ptr + 8, &direction, &seqnum)) | ||
| 317 | return GSS_S_BAD_SIG; | ||
| 318 | |||
| 319 | if ((kctx->initiate && direction != 0xff) || | ||
| 320 | (!kctx->initiate && direction != 0)) | ||
| 321 | return GSS_S_BAD_SIG; | ||
| 322 | |||
| 323 | if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { | ||
| 324 | struct crypto_blkcipher *cipher; | ||
| 325 | int err; | ||
| 326 | |||
| 327 | cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, | ||
| 328 | CRYPTO_ALG_ASYNC); | ||
| 329 | if (IS_ERR(cipher)) | ||
| 330 | return GSS_S_FAILURE; | ||
| 331 | |||
| 332 | krb5_rc4_setup_enc_key(kctx, cipher, seqnum); | ||
| 333 | |||
| 334 | err = gss_decrypt_xdr_buf(cipher, buf, crypt_offset); | ||
| 335 | crypto_free_blkcipher(cipher); | ||
| 336 | if (err) | ||
| 337 | return GSS_S_DEFECTIVE_TOKEN; | ||
| 338 | } else { | ||
| 339 | if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) | ||
| 340 | return GSS_S_DEFECTIVE_TOKEN; | ||
| 341 | } | ||
| 296 | 342 | ||
| 297 | if (kctx->gk5e->keyed_cksum) | 343 | if (kctx->gk5e->keyed_cksum) |
| 298 | cksumkey = kctx->cksum; | 344 | cksumkey = kctx->cksum; |
| @@ -316,14 +362,6 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
| 316 | 362 | ||
| 317 | /* do sequencing checks */ | 363 | /* do sequencing checks */ |
| 318 | 364 | ||
| 319 | if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, | ||
| 320 | ptr + 8, &direction, &seqnum)) | ||
| 321 | return GSS_S_BAD_SIG; | ||
| 322 | |||
| 323 | if ((kctx->initiate && direction != 0xff) || | ||
| 324 | (!kctx->initiate && direction != 0)) | ||
| 325 | return GSS_S_BAD_SIG; | ||
| 326 | |||
| 327 | /* Copy the data back to the right position. XXX: Would probably be | 365 | /* Copy the data back to the right position. XXX: Would probably be |
| 328 | * better to copy and encrypt at the same time. */ | 366 | * better to copy and encrypt at the same time. */ |
| 329 | 367 | ||
| @@ -521,6 +559,7 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset, | |||
| 521 | BUG(); | 559 | BUG(); |
| 522 | case ENCTYPE_DES_CBC_RAW: | 560 | case ENCTYPE_DES_CBC_RAW: |
| 523 | case ENCTYPE_DES3_CBC_RAW: | 561 | case ENCTYPE_DES3_CBC_RAW: |
| 562 | case ENCTYPE_ARCFOUR_HMAC: | ||
| 524 | return gss_wrap_kerberos_v1(kctx, offset, buf, pages); | 563 | return gss_wrap_kerberos_v1(kctx, offset, buf, pages); |
| 525 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 564 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
| 526 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 565 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
| @@ -538,6 +577,7 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf) | |||
| 538 | BUG(); | 577 | BUG(); |
| 539 | case ENCTYPE_DES_CBC_RAW: | 578 | case ENCTYPE_DES_CBC_RAW: |
| 540 | case ENCTYPE_DES3_CBC_RAW: | 579 | case ENCTYPE_DES3_CBC_RAW: |
| 580 | case ENCTYPE_ARCFOUR_HMAC: | ||
| 541 | return gss_unwrap_kerberos_v1(kctx, offset, buf); | 581 | return gss_unwrap_kerberos_v1(kctx, offset, buf); |
| 542 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 582 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
| 543 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 583 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
