1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 2001, 2008 by the Massachusetts Institute of Technology.
4 * Copyright 1993 by OpenVision Technologies, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appears in all copies and
9 * that both that copyright notice and this permission notice appear in
10 * supporting documentation, and that the name of OpenVision not be used
11 * in advertising or publicity pertaining to distribution of the software
12 * without specific, written prior permission. OpenVision makes no
13 * representations about the suitability of this software for any
14 * purpose. It is provided "as is" without express or implied warranty.
16 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
26 * Copyright (C) 1998 by the FundsXpress, INC.
28 * All rights reserved.
30 * Export of this software from the United States of America may require
31 * a specific license from the United States Government. It is the
32 * responsibility of any person or organization contemplating export to
33 * obtain such a license before exporting.
35 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
36 * distribute this software and its documentation for any purpose and
37 * without fee is hereby granted, provided that the above copyright
38 * notice appear in all copies and that both that copyright notice and
39 * this permission notice appear in supporting documentation, and that
40 * the name of FundsXpress. not be used in advertising or publicity pertaining
41 * to distribution of the software without specific, written prior
42 * permission. FundsXpress makes no representations about the suitability of
43 * this software for any purpose. It is provided "as is" without express
44 * or implied warranty.
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
52 #include "gssapiP_krb5.h"
57 static krb5_error_code
58 kg_copy_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey)
62 krb5_k_free_key(context, ctx->enc);
64 code = krb5_k_create_key(context, &subkey->keyblock, &ctx->enc);
68 krb5_k_free_key(context, ctx->seq);
70 code = krb5_k_create_key(context, &subkey->keyblock, &ctx->seq);
77 static krb5_error_code
78 kg_derive_des_enc_key(krb5_context context, krb5_key subkey, krb5_key *out)
81 krb5_keyblock *keyblock;
86 code = krb5_k_key_keyblock(context, subkey, &keyblock);
90 for (i = 0; i < keyblock->length; i++)
91 keyblock->contents[i] ^= 0xF0;
93 code = krb5_k_create_key(context, keyblock, out);
94 krb5_free_keyblock(context, keyblock);
99 kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey,
100 krb5_cksumtype *cksumtype)
102 krb5_error_code code;
105 assert(subkey != NULL);
110 if (ctx->enc == NULL) {
115 code = krb5int_c_mandatory_cksumtype(context, subkey->keyblock.enctype,
120 switch (subkey->keyblock.enctype) {
121 case ENCTYPE_DES_CBC_MD5:
122 case ENCTYPE_DES_CBC_MD4:
123 case ENCTYPE_DES_CBC_CRC:
124 krb5_k_free_key(context, ctx->seq);
125 code = krb5_k_create_key(context, &subkey->keyblock, &ctx->seq);
129 krb5_k_free_key(context, ctx->enc);
130 code = kg_derive_des_enc_key(context, subkey, &ctx->enc);
134 ctx->enc->keyblock.enctype = ENCTYPE_DES_CBC_RAW;
135 ctx->seq->keyblock.enctype = ENCTYPE_DES_CBC_RAW;
136 ctx->signalg = SGN_ALG_DES_MAC_MD5;
138 ctx->sealalg = SEAL_ALG_DES;
141 case ENCTYPE_DES3_CBC_SHA1:
142 code = kg_copy_keys(context, ctx, subkey);
146 ctx->enc->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
147 ctx->seq->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
148 ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
149 ctx->cksum_size = 20;
150 ctx->sealalg = SEAL_ALG_DES3KD;
152 case ENCTYPE_ARCFOUR_HMAC:
153 case ENCTYPE_ARCFOUR_HMAC_EXP:
154 /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" enctype,
155 * even though RFC 4757 treats it as one. */
156 code = kg_copy_keys(context, ctx, subkey);
160 ctx->signalg = SGN_ALG_HMAC_MD5;
162 ctx->sealalg = SEAL_ALG_MICROSOFT_RC4;
173 kg_confounder_size(krb5_context context, krb5_enctype enctype)
175 krb5_error_code code;
177 /* We special case rc4*/
178 if (enctype == ENCTYPE_ARCFOUR_HMAC || enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
180 code = krb5_c_block_size(context, enctype, &blocksize);
182 return(-1); /* XXX */
188 kg_make_confounder(krb5_context context, krb5_enctype enctype,
194 confsize = kg_confounder_size(context, enctype);
196 return KRB5_BAD_MSIZE;
198 lrandom.length = confsize;
199 lrandom.data = (char *)buf;
201 return(krb5_c_random_make_octets(context, &lrandom));
204 /* Set *data_out to a krb5_data structure containing iv, or to NULL if iv is
206 static krb5_error_code
207 iv_to_state(krb5_context context, krb5_key key, krb5_pointer iv,
208 krb5_data **data_out)
210 krb5_error_code code;
218 code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize);
222 data = k5alloc(sizeof(*data), &code);
225 code = alloc_data(data, blocksize);
230 memcpy(data->data, iv, blocksize);
236 kg_encrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv,
237 krb5_const_pointer in, krb5_pointer out, unsigned int length)
239 krb5_error_code code;
240 krb5_data *state, inputd;
241 krb5_enc_data outputd;
243 code = iv_to_state(context, key, iv, &state);
247 inputd.length = length;
248 inputd.data = (char *)in;
250 outputd.ciphertext.length = length;
251 outputd.ciphertext.data = out;
253 code = krb5_k_encrypt(context, key, usage, state, &inputd, &outputd);
254 krb5_free_data(context, state);
259 kg_encrypt_inplace(krb5_context context, krb5_key key, int usage,
260 krb5_pointer iv, krb5_pointer ptr, unsigned int length)
262 krb5_error_code code;
266 code = iv_to_state(context, key, iv, &state);
270 iov.flags = KRB5_CRYPTO_TYPE_DATA;
271 iov.data = make_data((void *)ptr, length);
272 code = krb5_k_encrypt_iov(context, key, usage, state, &iov, 1);
273 krb5_free_data(context, state);
277 /* length is the length of the cleartext. */
280 kg_decrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv,
281 krb5_const_pointer in, krb5_pointer out, unsigned int length)
283 krb5_error_code code;
284 krb5_data *state, outputd;
285 krb5_enc_data inputd;
287 code = iv_to_state(context, key, iv, &state);
291 inputd.enctype = ENCTYPE_UNKNOWN;
292 inputd.ciphertext.length = length;
293 inputd.ciphertext.data = (char *)in;
295 outputd.length = length;
298 code = krb5_k_decrypt(context, key, usage, state, &inputd, &outputd);
299 krb5_free_data(context, state);
304 kg_arcfour_docrypt(const krb5_keyblock *keyblock, int usage,
305 const unsigned char *kd_data, size_t kd_data_len,
306 const unsigned char *input_buf, size_t input_len,
307 unsigned char *output_buf)
309 krb5_data kd = make_data((char *) kd_data, kd_data_len);
310 krb5_crypto_iov kiov;
312 memcpy(output_buf, input_buf, input_len);
313 kiov.flags = KRB5_CRYPTO_TYPE_DATA;
314 kiov.data = make_data(output_buf, input_len);
315 return krb5int_arcfour_gsscrypt(keyblock, usage, &kd, &kiov, 1);
319 static krb5_error_code
320 kg_translate_iov_v1(krb5_context context, krb5_enctype enctype,
321 gss_iov_buffer_desc *iov, int iov_count,
322 krb5_crypto_iov **pkiov, size_t *pkiov_count)
324 gss_iov_buffer_desc *header;
325 gss_iov_buffer_desc *trailer;
328 krb5_crypto_iov *kiov;
334 conf_len = kg_confounder_size(context, enctype);
336 header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
337 assert(header != NULL);
339 if (header->buffer.length < conf_len)
340 return KRB5_BAD_MSIZE;
342 trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
343 assert(trailer == NULL || trailer->buffer.length == 0);
345 kiov_count = 3 + iov_count;
346 kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov));
350 /* For pre-CFX (raw enctypes) there is no krb5 header */
351 kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER;
352 kiov[i].data.length = 0;
353 kiov[i].data.data = NULL;
356 /* For pre-CFX, the confounder is at the end of the GSS header */
357 kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
358 kiov[i].data.length = conf_len;
359 kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len;
362 for (j = 0; j < iov_count; j++) {
363 kiov[i].flags = kg_translate_flag_iov(iov[j].type);
364 if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY)
367 kiov[i].data.length = iov[j].buffer.length;
368 kiov[i].data.data = (char *)iov[j].buffer.value;
372 kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
373 kiov[i].data.length = 0;
374 kiov[i].data.data = NULL;
384 * DCE_STYLE indicates actual RRC is EC + RRC
385 * EC is extra rotate count for DCE_STYLE, pad length otherwise
386 * RRC is rotate count.
388 static krb5_error_code
389 kg_translate_iov_v3(krb5_context context, int dce_style, size_t ec, size_t rrc,
390 krb5_enctype enctype, gss_iov_buffer_desc *iov,
391 int iov_count, krb5_crypto_iov **pkiov,
394 gss_iov_buffer_t header;
395 gss_iov_buffer_t trailer;
398 krb5_crypto_iov *kiov;
399 unsigned int k5_headerlen = 0, k5_trailerlen = 0;
400 size_t gss_headerlen, gss_trailerlen;
401 krb5_error_code code;
406 header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
407 assert(header != NULL);
409 trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
410 assert(trailer == NULL || rrc == 0);
412 code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER,
417 code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_TRAILER,
422 /* Check header and trailer sizes */
423 gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */
424 gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */
426 /* If we're caller without a trailer, we must rotate by trailer length */
427 if (trailer == NULL) {
428 size_t actual_rrc = rrc;
431 actual_rrc += ec; /* compensate for Windows bug */
433 if (actual_rrc != gss_trailerlen)
434 return KRB5_BAD_MSIZE;
436 gss_headerlen += gss_trailerlen;
439 if (trailer->buffer.length != gss_trailerlen)
440 return KRB5_BAD_MSIZE;
443 if (header->buffer.length != gss_headerlen)
444 return KRB5_BAD_MSIZE;
446 kiov_count = 3 + iov_count;
447 kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov));
452 * The krb5 header is located at the end of the GSS header.
454 kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER;
455 kiov[i].data.length = k5_headerlen;
456 kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen;
459 for (j = 0; j < iov_count; j++) {
460 kiov[i].flags = kg_translate_flag_iov(iov[j].type);
461 if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY)
464 kiov[i].data.length = iov[j].buffer.length;
465 kiov[i].data.data = (char *)iov[j].buffer.value;
470 * The EC and encrypted GSS header are placed in the trailer, which may
471 * be rotated directly after the plaintext header if no trailer buffer
474 kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
475 kiov[i].data.length = ec + 16; /* E(Header) */
477 kiov[i].data.data = (char *)header->buffer.value + 16;
479 kiov[i].data.data = (char *)trailer->buffer.value;
483 * The krb5 trailer is placed after the encrypted copy of the
484 * krb5 header (which may be in the GSS header or trailer).
486 kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
487 kiov[i].data.length = k5_trailerlen;
488 kiov[i].data.data = kiov[i - 1].data.data + ec + 16; /* E(Header) */
497 /* PROTO is 1 if CFX, 0 if pre-CFX */
498 static krb5_error_code
499 kg_translate_iov(krb5_context context, int proto, int dce_style, size_t ec,
500 size_t rrc, krb5_enctype enctype, gss_iov_buffer_desc *iov,
501 int iov_count, krb5_crypto_iov **pkiov, size_t *pkiov_count)
504 kg_translate_iov_v3(context, dce_style, ec, rrc, enctype,
505 iov, iov_count, pkiov, pkiov_count) :
506 kg_translate_iov_v1(context, enctype, iov, iov_count,
511 kg_encrypt_iov(krb5_context context, int proto, int dce_style, size_t ec,
512 size_t rrc, krb5_key key, int usage, krb5_pointer iv,
513 gss_iov_buffer_desc *iov, int iov_count)
515 krb5_error_code code;
518 krb5_crypto_iov *kiov;
520 code = iv_to_state(context, key, iv, &state);
524 code = kg_translate_iov(context, proto, dce_style, ec, rrc,
525 key->keyblock.enctype, iov, iov_count,
528 code = krb5_k_encrypt_iov(context, key, usage, state, kiov, kiov_len);
532 krb5_free_data(context, state);
536 /* length is the length of the cleartext. */
539 kg_decrypt_iov(krb5_context context, int proto, int dce_style, size_t ec,
540 size_t rrc, krb5_key key, int usage, krb5_pointer iv,
541 gss_iov_buffer_desc *iov, int iov_count)
543 krb5_error_code code;
546 krb5_crypto_iov *kiov;
548 code = iv_to_state(context, key, iv, &state);
552 code = kg_translate_iov(context, proto, dce_style, ec, rrc,
553 key->keyblock.enctype, iov, iov_count,
556 code = krb5_k_decrypt_iov(context, key, usage, state, kiov, kiov_len);
560 krb5_free_data(context, state);
565 kg_arcfour_docrypt_iov(krb5_context context, const krb5_keyblock *keyblock,
566 int usage, const unsigned char *kd_data,
567 size_t kd_data_len, gss_iov_buffer_desc *iov,
570 krb5_error_code code;
571 krb5_data kd = make_data((char *) kd_data, kd_data_len);
572 krb5_crypto_iov *kiov = NULL;
575 code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */,
576 0 /* ec */, 0 /* rrc */, keyblock->enctype,
577 iov, iov_count, &kiov, &kiov_len);
580 code = krb5int_arcfour_gsscrypt(keyblock, usage, &kd, kiov, kiov_len);
586 kg_translate_flag_iov(OM_uint32 type)
588 krb5_cryptotype ktype;
590 switch (GSS_IOV_BUFFER_TYPE(type)) {
591 case GSS_IOV_BUFFER_TYPE_DATA:
592 case GSS_IOV_BUFFER_TYPE_PADDING:
593 ktype = KRB5_CRYPTO_TYPE_DATA;
595 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
596 ktype = KRB5_CRYPTO_TYPE_SIGN_ONLY;
599 ktype = KRB5_CRYPTO_TYPE_EMPTY;
607 kg_locate_iov(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)
610 gss_iov_buffer_t p = GSS_C_NO_IOV_BUFFER;
612 if (iov == GSS_C_NO_IOV_BUFFER)
613 return GSS_C_NO_IOV_BUFFER;
615 for (i = iov_count - 1; i >= 0; i--) {
616 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == type) {
617 if (p == GSS_C_NO_IOV_BUFFER)
620 return GSS_C_NO_IOV_BUFFER;
627 /* Return the IOV where the GSSAPI token header should be placed (and possibly
628 * the checksum as well, depending on the token type). */
630 kg_locate_header_iov(gss_iov_buffer_desc *iov, int iov_count, int toktype)
632 if (toktype == KG_TOK_MIC_MSG)
633 return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_MIC_TOKEN);
635 return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
639 kg_iov_msglen(gss_iov_buffer_desc *iov, int iov_count, size_t *data_length_p,
640 size_t *assoc_data_length_p)
643 size_t data_length = 0, assoc_data_length = 0;
645 assert(iov != GSS_C_NO_IOV_BUFFER);
647 *data_length_p = *assoc_data_length_p = 0;
649 for (i = 0; i < iov_count; i++) {
650 OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[i].type);
652 if (type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
653 assoc_data_length += iov[i].buffer.length;
655 if (type == GSS_IOV_BUFFER_TYPE_DATA ||
656 type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
657 data_length += iov[i].buffer.length;
660 *data_length_p = data_length;
661 *assoc_data_length_p = assoc_data_length;
665 kg_release_iov(gss_iov_buffer_desc *iov, int iov_count)
669 assert(iov != GSS_C_NO_IOV_BUFFER);
671 for (i = 0; i < iov_count; i++) {
672 if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
673 gssalloc_free(iov[i].buffer.value);
674 iov[i].buffer.length = 0;
675 iov[i].buffer.value = NULL;
676 iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
682 kg_fixup_padding_iov(OM_uint32 *minor_status, gss_iov_buffer_desc *iov,
685 gss_iov_buffer_t padding = NULL;
686 gss_iov_buffer_t data = NULL;
687 size_t padlength, relative_padlength;
690 data = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_DATA);
691 padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
695 return GSS_S_COMPLETE;
698 if (padding == NULL || padding->buffer.length == 0) {
699 *minor_status = EINVAL;
700 return GSS_S_FAILURE;
703 p = (unsigned char *)padding->buffer.value;
704 padlength = p[padding->buffer.length - 1];
706 if (data->buffer.length + padding->buffer.length < padlength ||
708 *minor_status = (OM_uint32)KRB5_BAD_MSIZE;
709 return GSS_S_DEFECTIVE_TOKEN;
713 * kg_unseal_stream_iov() will place one byte of padding in the
714 * padding buffer; its true value is unknown until after decryption.
716 * relative_padlength contains the number of bytes to compensate the
717 * padding and data buffers by; it will be zero if the caller manages
718 * the padding length.
720 * If the caller manages the padding length, then relative_padlength
723 * eg. if the buffers are structured as follows:
729 * after compensation they would look like:
735 relative_padlength = padlength - padding->buffer.length;
737 assert(data->buffer.length >= relative_padlength);
739 data->buffer.length -= relative_padlength;
741 kg_release_iov(padding, 1);
742 padding->buffer.length = 0;
743 padding->buffer.value = NULL;
745 return GSS_S_COMPLETE;
749 kg_integ_only_iov(gss_iov_buffer_desc *iov, int iov_count)
752 krb5_boolean has_conf_data = FALSE;
754 assert(iov != GSS_C_NO_IOV_BUFFER);
756 for (i = 0; i < iov_count; i++) {
757 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) {
758 has_conf_data = TRUE;
763 return (has_conf_data == FALSE);
767 kg_allocate_iov(gss_iov_buffer_t iov, size_t size)
769 assert(iov != GSS_C_NO_IOV_BUFFER);
770 assert(iov->type & GSS_IOV_BUFFER_FLAG_ALLOCATE);
772 iov->buffer.length = size;
773 iov->buffer.value = gssalloc_malloc(size);
774 if (iov->buffer.value == NULL) {
775 iov->buffer.length = 0;
779 iov->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED;