3 * The Regents of the University of Michigan
6 * Permission is granted to use, copy, create derivative works
7 * and redistribute this software and such derivative works
8 * for any purpose, so long as the name of The University of
9 * Michigan is not used in any advertising or publicity
10 * pertaining to the use of distribution of this software
11 * without specific, written prior authorization. If the
12 * above copyright notice or any other identification of the
13 * University of Michigan is included in any copy of any
14 * portion of this software, then the disclaimer below must
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
31 #include <linux/types.h>
32 #include <linux/jiffies.h>
33 #include <linux/sunrpc/gss_krb5.h>
34 #include <linux/random.h>
35 #include <linux/pagemap.h>
36 #include <linux/crypto.h>
39 # define RPCDBG_FACILITY RPCDBG_AUTH
43 gss_krb5_padding(int blocksize
, int length
)
45 return blocksize
- (length
% blocksize
);
49 gss_krb5_add_padding(struct xdr_buf
*buf
, int offset
, int blocksize
)
51 int padding
= gss_krb5_padding(blocksize
, buf
->len
- offset
);
55 if (buf
->page_len
|| buf
->tail
[0].iov_len
)
59 p
= iov
->iov_base
+ iov
->iov_len
;
60 iov
->iov_len
+= padding
;
62 memset(p
, padding
, padding
);
66 gss_krb5_remove_padding(struct xdr_buf
*buf
, int blocksize
)
70 size_t len
= buf
->len
;
72 if (len
<= buf
->head
[0].iov_len
) {
73 pad
= *(u8
*)(buf
->head
[0].iov_base
+ len
- 1);
74 if (pad
> buf
->head
[0].iov_len
)
76 buf
->head
[0].iov_len
-= pad
;
79 len
-= buf
->head
[0].iov_len
;
80 if (len
<= buf
->page_len
) {
81 unsigned int last
= (buf
->page_base
+ len
- 1)
83 unsigned int offset
= (buf
->page_base
+ len
- 1)
84 & (PAGE_CACHE_SIZE
- 1);
85 ptr
= kmap_atomic(buf
->pages
[last
], KM_USER0
);
86 pad
= *(ptr
+ offset
);
87 kunmap_atomic(ptr
, KM_USER0
);
91 BUG_ON(len
> buf
->tail
[0].iov_len
);
92 pad
= *(u8
*)(buf
->tail
[0].iov_base
+ len
- 1);
104 gss_krb5_make_confounder(char *p
, u32 conflen
)
109 /* rfc1964 claims this should be "random". But all that's really
110 * necessary is that it be unique. And not even that is necessary in
111 * our case since our "gssapi" implementation exists only to support
112 * rpcsec_gss, so we know that the only buffers we will ever encrypt
113 * already begin with a unique sequence number. Just to hedge my bets
114 * I'll make a half-hearted attempt at something unique, but ensuring
115 * uniqueness would mean worrying about atomicity and rollover, and I
116 * don't care enough. */
118 /* initialize to random value */
121 i
= (i
<< 32) | random32();
136 /* Assumptions: the head and tail of inbuf are ours to play with.
137 * The pages, however, may be real pages in the page cache and we replace
138 * them with scratch pages from **pages before writing to them. */
142 gss_wrap_kerberos_v1(struct krb5_ctx
*kctx
, int offset
,
143 struct xdr_buf
*buf
, struct page
**pages
)
145 char cksumdata
[GSS_KRB5_MAX_CKSUM_LEN
];
146 struct xdr_netobj md5cksum
= {.len
= sizeof(cksumdata
),
148 int blocksize
= 0, plainlen
;
149 unsigned char *ptr
, *msg_start
;
152 struct page
**tmp_pages
;
155 u32 conflen
= kctx
->gk5e
->conflen
;
157 dprintk("RPC: %s\n", __func__
);
161 blocksize
= crypto_blkcipher_blocksize(kctx
->enc
);
162 gss_krb5_add_padding(buf
, offset
, blocksize
);
163 BUG_ON((buf
->len
- offset
) % blocksize
);
164 plainlen
= conflen
+ buf
->len
- offset
;
166 headlen
= g_token_size(&kctx
->mech_used
,
167 GSS_KRB5_TOK_HDR_LEN
+ kctx
->gk5e
->cksumlength
+ plainlen
) -
170 ptr
= buf
->head
[0].iov_base
+ offset
;
171 /* shift data to make room for header. */
172 xdr_extend_head(buf
, offset
, headlen
);
174 BUG_ON((buf
->len
- offset
- headlen
) % blocksize
);
176 g_make_token_header(&kctx
->mech_used
,
177 GSS_KRB5_TOK_HDR_LEN
+
178 kctx
->gk5e
->cksumlength
+ plainlen
, &ptr
);
181 /* ptr now at header described in rfc 1964, section 1.2.1: */
182 ptr
[0] = (unsigned char) ((KG_TOK_WRAP_MSG
>> 8) & 0xff);
183 ptr
[1] = (unsigned char) (KG_TOK_WRAP_MSG
& 0xff);
185 msg_start
= ptr
+ GSS_KRB5_TOK_HDR_LEN
+ kctx
->gk5e
->cksumlength
;
187 *(__be16
*)(ptr
+ 2) = cpu_to_le16(kctx
->gk5e
->signalg
);
188 memset(ptr
+ 4, 0xff, 4);
189 *(__be16
*)(ptr
+ 4) = cpu_to_le16(kctx
->gk5e
->sealalg
);
191 gss_krb5_make_confounder(msg_start
, conflen
);
193 if (kctx
->gk5e
->keyed_cksum
)
194 cksumkey
= kctx
->cksum
;
199 tmp_pages
= buf
->pages
;
201 if (make_checksum(kctx
, ptr
, 8, buf
, offset
+ headlen
- conflen
,
202 cksumkey
, KG_USAGE_SEAL
, &md5cksum
))
203 return GSS_S_FAILURE
;
204 buf
->pages
= tmp_pages
;
206 memcpy(ptr
+ GSS_KRB5_TOK_HDR_LEN
, md5cksum
.data
, md5cksum
.len
);
208 spin_lock(&krb5_seq_lock
);
209 seq_send
= kctx
->seq_send
++;
210 spin_unlock(&krb5_seq_lock
);
212 if ((krb5_make_seq_num(kctx
, kctx
->seq
, kctx
->initiate
? 0 : 0xff,
213 seq_send
, ptr
+ GSS_KRB5_TOK_HDR_LEN
, ptr
+ 8)))
214 return GSS_S_FAILURE
;
216 if (kctx
->enctype
== ENCTYPE_ARCFOUR_HMAC
) {
217 struct crypto_blkcipher
*cipher
;
219 cipher
= crypto_alloc_blkcipher(kctx
->gk5e
->encrypt_name
, 0,
222 return GSS_S_FAILURE
;
224 krb5_rc4_setup_enc_key(kctx
, cipher
, seq_send
);
226 err
= gss_encrypt_xdr_buf(cipher
, buf
,
227 offset
+ headlen
- conflen
, pages
);
228 crypto_free_blkcipher(cipher
);
230 return GSS_S_FAILURE
;
232 if (gss_encrypt_xdr_buf(kctx
->enc
, buf
,
233 offset
+ headlen
- conflen
, pages
))
234 return GSS_S_FAILURE
;
237 return (kctx
->endtime
< now
) ? GSS_S_CONTEXT_EXPIRED
: GSS_S_COMPLETE
;
241 gss_unwrap_kerberos_v1(struct krb5_ctx
*kctx
, int offset
, struct xdr_buf
*buf
)
245 char cksumdata
[GSS_KRB5_MAX_CKSUM_LEN
];
246 struct xdr_netobj md5cksum
= {.len
= sizeof(cksumdata
),
253 void *data_start
, *orig_start
;
256 u32 conflen
= kctx
->gk5e
->conflen
;
260 dprintk("RPC: gss_unwrap_kerberos\n");
262 ptr
= (u8
*)buf
->head
[0].iov_base
+ offset
;
263 if (g_verify_token_header(&kctx
->mech_used
, &bodysize
, &ptr
,
265 return GSS_S_DEFECTIVE_TOKEN
;
267 if ((ptr
[0] != ((KG_TOK_WRAP_MSG
>> 8) & 0xff)) ||
268 (ptr
[1] != (KG_TOK_WRAP_MSG
& 0xff)))
269 return GSS_S_DEFECTIVE_TOKEN
;
272 /* get the sign and seal algorithms */
274 signalg
= ptr
[2] + (ptr
[3] << 8);
275 if (signalg
!= kctx
->gk5e
->signalg
)
276 return GSS_S_DEFECTIVE_TOKEN
;
278 sealalg
= ptr
[4] + (ptr
[5] << 8);
279 if (sealalg
!= kctx
->gk5e
->sealalg
)
280 return GSS_S_DEFECTIVE_TOKEN
;
282 if ((ptr
[6] != 0xff) || (ptr
[7] != 0xff))
283 return GSS_S_DEFECTIVE_TOKEN
;
286 * Data starts after token header and checksum. ptr points
287 * to the beginning of the token header
289 crypt_offset
= ptr
+ (GSS_KRB5_TOK_HDR_LEN
+ kctx
->gk5e
->cksumlength
) -
290 (unsigned char *)buf
->head
[0].iov_base
;
293 * Need plaintext seqnum to derive encryption key for arcfour-hmac
295 if (krb5_get_seq_num(kctx
, ptr
+ GSS_KRB5_TOK_HDR_LEN
,
296 ptr
+ 8, &direction
, &seqnum
))
297 return GSS_S_BAD_SIG
;
299 if ((kctx
->initiate
&& direction
!= 0xff) ||
300 (!kctx
->initiate
&& direction
!= 0))
301 return GSS_S_BAD_SIG
;
303 if (kctx
->enctype
== ENCTYPE_ARCFOUR_HMAC
) {
304 struct crypto_blkcipher
*cipher
;
307 cipher
= crypto_alloc_blkcipher(kctx
->gk5e
->encrypt_name
, 0,
310 return GSS_S_FAILURE
;
312 krb5_rc4_setup_enc_key(kctx
, cipher
, seqnum
);
314 err
= gss_decrypt_xdr_buf(cipher
, buf
, crypt_offset
);
315 crypto_free_blkcipher(cipher
);
317 return GSS_S_DEFECTIVE_TOKEN
;
319 if (gss_decrypt_xdr_buf(kctx
->enc
, buf
, crypt_offset
))
320 return GSS_S_DEFECTIVE_TOKEN
;
323 if (kctx
->gk5e
->keyed_cksum
)
324 cksumkey
= kctx
->cksum
;
328 if (make_checksum(kctx
, ptr
, 8, buf
, crypt_offset
,
329 cksumkey
, KG_USAGE_SEAL
, &md5cksum
))
330 return GSS_S_FAILURE
;
332 if (memcmp(md5cksum
.data
, ptr
+ GSS_KRB5_TOK_HDR_LEN
,
333 kctx
->gk5e
->cksumlength
))
334 return GSS_S_BAD_SIG
;
336 /* it got through unscathed. Make sure the context is unexpired */
340 if (now
> kctx
->endtime
)
341 return GSS_S_CONTEXT_EXPIRED
;
343 /* do sequencing checks */
346 blocksize
= crypto_blkcipher_blocksize(kctx
->enc
);
347 data_start
= ptr
+ (GSS_KRB5_TOK_HDR_LEN
+ kctx
->gk5e
->cksumlength
) +
349 orig_start
= buf
->head
[0].iov_base
+ offset
;
350 data_len
= (buf
->head
[0].iov_base
+ buf
->head
[0].iov_len
) - data_start
;
351 memmove(orig_start
, data_start
, data_len
);
352 buf
->head
[0].iov_len
-= (data_start
- orig_start
);
353 buf
->len
-= (data_start
- orig_start
);
355 if (gss_krb5_remove_padding(buf
, blocksize
))
356 return GSS_S_DEFECTIVE_TOKEN
;
358 return GSS_S_COMPLETE
;
362 * We cannot currently handle tokens with rotated data. We need a
363 * generalized routine to rotate the data in place. It is anticipated
364 * that we won't encounter rotated data in the general case.
367 rotate_left(struct krb5_ctx
*kctx
, u32 offset
, struct xdr_buf
*buf
, u16 rrc
)
369 unsigned int realrrc
= rrc
% (buf
->len
- offset
- GSS_KRB5_TOK_HDR_LEN
);
374 dprintk("%s: cannot process token with rotated data: "
375 "rrc %u, realrrc %u\n", __func__
, rrc
, realrrc
);
380 gss_wrap_kerberos_v2(struct krb5_ctx
*kctx
, u32 offset
,
381 struct xdr_buf
*buf
, struct page
**pages
)
387 __be16
*be16ptr
, ec
= 0;
391 dprintk("RPC: %s\n", __func__
);
393 if (kctx
->gk5e
->encrypt_v2
== NULL
)
394 return GSS_S_FAILURE
;
396 /* make room for gss token header */
397 if (xdr_extend_head(buf
, offset
, GSS_KRB5_TOK_HDR_LEN
))
398 return GSS_S_FAILURE
;
400 /* construct gss token header */
401 ptr
= plainhdr
= buf
->head
[0].iov_base
+ offset
;
402 *ptr
++ = (unsigned char) ((KG2_TOK_WRAP
>>8) & 0xff);
403 *ptr
++ = (unsigned char) (KG2_TOK_WRAP
& 0xff);
405 if ((kctx
->flags
& KRB5_CTX_FLAG_INITIATOR
) == 0)
406 flags
|= KG2_TOKEN_FLAG_SENTBYACCEPTOR
;
407 if ((kctx
->flags
& KRB5_CTX_FLAG_ACCEPTOR_SUBKEY
) != 0)
408 flags
|= KG2_TOKEN_FLAG_ACCEPTORSUBKEY
;
409 /* We always do confidentiality in wrap tokens */
410 flags
|= KG2_TOKEN_FLAG_SEALED
;
414 be16ptr
= (__be16
*)ptr
;
416 blocksize
= crypto_blkcipher_blocksize(kctx
->acceptor_enc
);
417 *be16ptr
++ = cpu_to_be16(ec
);
418 /* "inner" token header always uses 0 for RRC */
419 *be16ptr
++ = cpu_to_be16(0);
421 be64ptr
= (__be64
*)be16ptr
;
422 spin_lock(&krb5_seq_lock
);
423 *be64ptr
= cpu_to_be64(kctx
->seq_send64
++);
424 spin_unlock(&krb5_seq_lock
);
426 err
= (*kctx
->gk5e
->encrypt_v2
)(kctx
, offset
, buf
, ec
, pages
);
431 return (kctx
->endtime
< now
) ? GSS_S_CONTEXT_EXPIRED
: GSS_S_COMPLETE
;
435 gss_unwrap_kerberos_v2(struct krb5_ctx
*kctx
, int offset
, struct xdr_buf
*buf
)
443 u32 headskip
, tailskip
;
444 u8 decrypted_hdr
[GSS_KRB5_TOK_HDR_LEN
];
445 unsigned int movelen
;
448 dprintk("RPC: %s\n", __func__
);
450 if (kctx
->gk5e
->decrypt_v2
== NULL
)
451 return GSS_S_FAILURE
;
453 ptr
= buf
->head
[0].iov_base
+ offset
;
455 if (be16_to_cpu(*((__be16
*)ptr
)) != KG2_TOK_WRAP
)
456 return GSS_S_DEFECTIVE_TOKEN
;
459 if ((!kctx
->initiate
&& (flags
& KG2_TOKEN_FLAG_SENTBYACCEPTOR
)) ||
460 (kctx
->initiate
&& !(flags
& KG2_TOKEN_FLAG_SENTBYACCEPTOR
)))
461 return GSS_S_BAD_SIG
;
463 if ((flags
& KG2_TOKEN_FLAG_SEALED
) == 0) {
464 dprintk("%s: token missing expected sealed flag\n", __func__
);
465 return GSS_S_DEFECTIVE_TOKEN
;
469 return GSS_S_DEFECTIVE_TOKEN
;
471 ec
= be16_to_cpup((__be16
*)(ptr
+ 4));
472 rrc
= be16_to_cpup((__be16
*)(ptr
+ 6));
474 seqnum
= be64_to_cpup((__be64
*)(ptr
+ 8));
477 err
= rotate_left(kctx
, offset
, buf
, rrc
);
479 return GSS_S_FAILURE
;
482 err
= (*kctx
->gk5e
->decrypt_v2
)(kctx
, offset
, buf
,
483 &headskip
, &tailskip
);
485 return GSS_S_FAILURE
;
488 * Retrieve the decrypted gss token header and verify
489 * it against the original
491 err
= read_bytes_from_xdr_buf(buf
,
492 buf
->len
- GSS_KRB5_TOK_HDR_LEN
- tailskip
,
493 decrypted_hdr
, GSS_KRB5_TOK_HDR_LEN
);
495 dprintk("%s: error %u getting decrypted_hdr\n", __func__
, err
);
496 return GSS_S_FAILURE
;
498 if (memcmp(ptr
, decrypted_hdr
, 6)
499 || memcmp(ptr
+ 8, decrypted_hdr
+ 8, 8)) {
500 dprintk("%s: token hdr, plaintext hdr mismatch!\n", __func__
);
501 return GSS_S_FAILURE
;
504 /* do sequencing checks */
506 /* it got through unscathed. Make sure the context is unexpired */
508 if (now
> kctx
->endtime
)
509 return GSS_S_CONTEXT_EXPIRED
;
512 * Move the head data back to the right position in xdr_buf.
513 * We ignore any "ec" data since it might be in the head or
514 * the tail, and we really don't need to deal with it.
515 * Note that buf->head[0].iov_len may indicate the available
516 * head buffer space rather than that actually occupied.
518 movelen
= min_t(unsigned int, buf
->head
[0].iov_len
, buf
->len
);
519 movelen
-= offset
+ GSS_KRB5_TOK_HDR_LEN
+ headskip
;
520 BUG_ON(offset
+ GSS_KRB5_TOK_HDR_LEN
+ headskip
+ movelen
>
521 buf
->head
[0].iov_len
);
522 memmove(ptr
, ptr
+ GSS_KRB5_TOK_HDR_LEN
+ headskip
, movelen
);
523 buf
->head
[0].iov_len
-= GSS_KRB5_TOK_HDR_LEN
+ headskip
;
524 buf
->len
-= GSS_KRB5_TOK_HDR_LEN
+ headskip
;
526 return GSS_S_COMPLETE
;
530 gss_wrap_kerberos(struct gss_ctx
*gctx
, int offset
,
531 struct xdr_buf
*buf
, struct page
**pages
)
533 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
535 switch (kctx
->enctype
) {
538 case ENCTYPE_DES_CBC_RAW
:
539 case ENCTYPE_DES3_CBC_RAW
:
540 case ENCTYPE_ARCFOUR_HMAC
:
541 return gss_wrap_kerberos_v1(kctx
, offset
, buf
, pages
);
542 case ENCTYPE_AES128_CTS_HMAC_SHA1_96
:
543 case ENCTYPE_AES256_CTS_HMAC_SHA1_96
:
544 return gss_wrap_kerberos_v2(kctx
, offset
, buf
, pages
);
549 gss_unwrap_kerberos(struct gss_ctx
*gctx
, int offset
, struct xdr_buf
*buf
)
551 struct krb5_ctx
*kctx
= gctx
->internal_ctx_id
;
553 switch (kctx
->enctype
) {
556 case ENCTYPE_DES_CBC_RAW
:
557 case ENCTYPE_DES3_CBC_RAW
:
558 case ENCTYPE_ARCFOUR_HMAC
:
559 return gss_unwrap_kerberos_v1(kctx
, offset
, buf
);
560 case ENCTYPE_AES128_CTS_HMAC_SHA1_96
:
561 case ENCTYPE_AES256_CTS_HMAC_SHA1_96
:
562 return gss_unwrap_kerberos_v2(kctx
, offset
, buf
);