cfx.c
来自「samba最新软件」· C语言 代码 · 共 879 行 · 第 1/2 页
C
879 行
/* * Copyright (c) 2003, PADL Software Pty Ltd. * All rights reserved. * * 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, this list of conditions and the following disclaimer. * * 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. Neither the name of PADL Software nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "krb5/gsskrb5_locl.h"RCSID("$Id: cfx.c 19031 2006-11-13 18:02:57Z lha $");/* * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt */#define CFXSentByAcceptor (1 << 0)#define CFXSealed (1 << 1)#define CFXAcceptorSubkey (1 << 2)krb5_error_code_gsskrb5cfx_wrap_length_cfx(krb5_context context, krb5_crypto crypto, int conf_req_flag, size_t input_length, size_t *output_length, size_t *cksumsize, uint16_t *padlength){ krb5_error_code ret; krb5_cksumtype type; /* 16-byte header is always first */ *output_length = sizeof(gss_cfx_wrap_token_desc); *padlength = 0; ret = krb5_crypto_get_checksum_type(context, crypto, &type); if (ret) return ret; ret = krb5_checksumsize(context, type, cksumsize); if (ret) return ret; if (conf_req_flag) { size_t padsize; /* Header is concatenated with data before encryption */ input_length += sizeof(gss_cfx_wrap_token_desc); ret = krb5_crypto_getpadsize(context, crypto, &padsize); if (ret) { return ret; } if (padsize > 1) { /* XXX check this */ *padlength = padsize - (input_length % padsize); /* We add the pad ourselves (noted here for completeness only) */ input_length += *padlength; } *output_length += krb5_get_wrapped_length(context, crypto, input_length); } else { /* Checksum is concatenated with data */ *output_length += input_length + *cksumsize; } assert(*output_length > input_length); return 0;}krb5_error_code_gsskrb5cfx_max_wrap_length_cfx(krb5_context context, krb5_crypto crypto, int conf_req_flag, size_t input_length, OM_uint32 *output_length){ krb5_error_code ret; *output_length = 0; /* 16-byte header is always first */ if (input_length < 16) return 0; input_length -= 16; if (conf_req_flag) { size_t wrapped_size, sz; wrapped_size = input_length + 1; do { wrapped_size--; sz = krb5_get_wrapped_length(context, crypto, wrapped_size); } while (wrapped_size && sz > input_length); if (wrapped_size == 0) { *output_length = 0; return 0; } /* inner header */ if (wrapped_size < 16) { *output_length = 0; return 0; } wrapped_size -= 16; *output_length = wrapped_size; } else { krb5_cksumtype type; size_t cksumsize; ret = krb5_crypto_get_checksum_type(context, crypto, &type); if (ret) return ret; ret = krb5_checksumsize(context, type, &cksumsize); if (ret) return ret; if (input_length < cksumsize) return 0; /* Checksum is concatenated with data */ *output_length = input_length - cksumsize; } return 0;}OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, const gsskrb5_ctx context_handle, krb5_context context, int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size, OM_uint32 *max_input_size, krb5_keyblock *key){ krb5_error_code ret; krb5_crypto crypto; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret != 0) { *minor_status = ret; return GSS_S_FAILURE; } ret = _gsskrb5cfx_max_wrap_length_cfx(context, crypto, conf_req_flag, req_output_size, max_input_size); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); return GSS_S_FAILURE; } krb5_crypto_destroy(context, crypto); return GSS_S_COMPLETE;}/* * Rotate "rrc" bytes to the front or back */static krb5_error_coderrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate){ u_char *tmp, buf[256]; size_t left; if (len == 0) return 0; rrc %= len; if (rrc == 0) return 0; left = len - rrc; if (rrc <= sizeof(buf)) { tmp = buf; } else { tmp = malloc(rrc); if (tmp == NULL) return ENOMEM; } if (unrotate) { memcpy(tmp, data, rrc); memmove(data, (u_char *)data + rrc, left); memcpy((u_char *)data + left, tmp, rrc); } else { memcpy(tmp, (u_char *)data + left, rrc); memmove((u_char *)data + rrc, data, left); memcpy(data, tmp, rrc); } if (rrc > sizeof(buf)) free(tmp); return 0;}OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, const gsskrb5_ctx context_handle, krb5_context context, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer, krb5_keyblock *key){ krb5_crypto crypto; gss_cfx_wrap_token token; krb5_error_code ret; unsigned usage; krb5_data cipher; size_t wrapped_len, cksumsize; uint16_t padlength, rrc = 0; int32_t seq_number; u_char *p; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret != 0) { *minor_status = ret; return GSS_S_FAILURE; } ret = _gsskrb5cfx_wrap_length_cfx(context, crypto, conf_req_flag, input_message_buffer->length, &wrapped_len, &cksumsize, &padlength); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); return GSS_S_FAILURE; } /* Always rotate encrypted token (if any) and checksum to header */ rrc = (conf_req_flag ? sizeof(*token) : 0) + (uint16_t)cksumsize; output_message_buffer->length = wrapped_len; output_message_buffer->value = malloc(output_message_buffer->length); if (output_message_buffer->value == NULL) { *minor_status = ENOMEM; krb5_crypto_destroy(context, crypto); return GSS_S_FAILURE; } p = output_message_buffer->value; token = (gss_cfx_wrap_token)p; token->TOK_ID[0] = 0x05; token->TOK_ID[1] = 0x04; token->Flags = 0; token->Filler = 0xFF; if ((context_handle->more_flags & LOCAL) == 0) token->Flags |= CFXSentByAcceptor; if (context_handle->more_flags & ACCEPTOR_SUBKEY) token->Flags |= CFXAcceptorSubkey; if (conf_req_flag) { /* * In Wrap tokens with confidentiality, the EC field is * used to encode the size (in bytes) of the random filler. */ token->Flags |= CFXSealed; token->EC[0] = (padlength >> 8) & 0xFF; token->EC[1] = (padlength >> 0) & 0xFF; } else { /* * In Wrap tokens without confidentiality, the EC field is * used to encode the size (in bytes) of the trailing * checksum. * * This is not used in the checksum calcuation itself, * because the checksum length could potentially vary * depending on the data length. */ token->EC[0] = 0; token->EC[1] = 0; } /* * In Wrap tokens that provide for confidentiality, the RRC * field in the header contains the hex value 00 00 before * encryption. * * In Wrap tokens that do not provide for confidentiality, * both the EC and RRC fields in the appended checksum * contain the hex value 00 00 for the purpose of calculating * the checksum. */ token->RRC[0] = 0; token->RRC[1] = 0; HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); krb5_auth_con_getlocalseqnumber(context, context_handle->auth_context, &seq_number); _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); krb5_auth_con_setlocalseqnumber(context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); /* * If confidentiality is requested, the token header is * appended to the plaintext before encryption; the resulting * token is {"header" | encrypt(plaintext | pad | "header")}. * * If no confidentiality is requested, the checksum is * calculated over the plaintext concatenated with the * token header. */ if (context_handle->more_flags & LOCAL) { usage = KRB5_KU_USAGE_INITIATOR_SEAL; } else { usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; } if (conf_req_flag) { /* * Any necessary padding is added here to ensure that the * encrypted token header is always at the end of the * ciphertext. * * The specification does not require that the padding * bytes are initialized. */ p += sizeof(*token); memcpy(p, input_message_buffer->value, input_message_buffer->length); memset(p + input_message_buffer->length, 0xFF, padlength); memcpy(p + input_message_buffer->length + padlength, token, sizeof(*token)); ret = krb5_encrypt(context, crypto, usage, p, input_message_buffer->length + padlength + sizeof(*token), &cipher); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } assert(sizeof(*token) + cipher.length == wrapped_len); token->RRC[0] = (rrc >> 8) & 0xFF; token->RRC[1] = (rrc >> 0) & 0xFF; ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } memcpy(p, cipher.data, cipher.length); krb5_data_free(&cipher); } else { char *buf; Checksum cksum; buf = malloc(input_message_buffer->length + sizeof(*token)); if (buf == NULL) { *minor_status = ENOMEM; krb5_crypto_destroy(context, crypto); _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } memcpy(buf, input_message_buffer->value, input_message_buffer->length); memcpy(buf + input_message_buffer->length, token, sizeof(*token)); ret = krb5_create_checksum(context, crypto, usage, 0, buf, input_message_buffer->length + sizeof(*token), &cksum); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); _gsskrb5_release_buffer(minor_status, output_message_buffer); free(buf); return GSS_S_FAILURE; } free(buf); assert(cksum.checksum.length == cksumsize); token->EC[0] = (cksum.checksum.length >> 8) & 0xFF; token->EC[1] = (cksum.checksum.length >> 0) & 0xFF; token->RRC[0] = (rrc >> 8) & 0xFF; token->RRC[1] = (rrc >> 0) & 0xFF; p += sizeof(*token); memcpy(p, input_message_buffer->value, input_message_buffer->length); memcpy(p + input_message_buffer->length, cksum.checksum.data, cksum.checksum.length); ret = rrc_rotate(p, input_message_buffer->length + cksum.checksum.length, rrc, FALSE); if (ret != 0) { *minor_status = ret; krb5_crypto_destroy(context, crypto); _gsskrb5_release_buffer(minor_status, output_message_buffer); free_Checksum(&cksum); return GSS_S_FAILURE; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?