ssize_t do_read (int fd, void *buf, size_t sz, void *ivec) { if (do_encrypt) { #ifdef KRB5 if(auth_method == AUTH_KRB5) { krb5_error_code ret; uint32_t len, outer_len; int status; krb5_data data; void *edata; ret = krb5_net_read (context, &fd, &len, 4); if (ret <= 0) return ret; len = ntohl(len); if (len > sz) abort (); /* ivec will be non null for protocol version 2 */ if(ivec != NULL) outer_len = krb5_get_wrapped_length (context, crypto, len + 4); else outer_len = krb5_get_wrapped_length (context, crypto, len); edata = malloc (outer_len); if (edata == NULL) errx (1, "malloc: cannot allocate %u bytes", outer_len); ret = krb5_net_read (context, &fd, edata, outer_len); if (ret <= 0) { free(edata); return ret; } status = krb5_decrypt_ivec(context, crypto, key_usage, edata, outer_len, &data, ivec); free (edata); if (status) krb5_err (context, 1, status, "decrypting data"); if(ivec != NULL) { unsigned long l; if(data.length < len + 4) errx (1, "data received is too short"); _krb5_get_int(data.data, &l, 4); if(l != len) errx (1, "inconsistency in received data"); memcpy (buf, (unsigned char *)data.data+4, len); } else memcpy (buf, data.data, len); krb5_data_free (&data); return len; } else #endif /* KRB5 */ abort (); } else return read (fd, buf, sz); }
static void test_wrapping(krb5_context context, size_t min_size, size_t max_size, size_t step, krb5_enctype etype) { krb5_error_code ret; krb5_keyblock key; krb5_crypto crypto; krb5_data data; char *etype_name; void *buf; size_t size; ret = krb5_generate_random_keyblock(context, etype, &key); if (ret) krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); ret = krb5_enctype_to_string(context, etype, &etype_name); if (ret) krb5_err(context, 1, ret, "krb5_enctype_to_string"); buf = malloc(max_size); if (buf == NULL) krb5_errx(context, 1, "out of memory"); memset(buf, 0, max_size); ret = krb5_crypto_init(context, &key, 0, &crypto); if (ret) krb5_err(context, 1, ret, "krb5_crypto_init"); for (size = min_size; size < max_size; size += step) { size_t wrapped_size; ret = krb5_encrypt(context, crypto, 0, buf, size, &data); if (ret) krb5_err(context, 1, ret, "encrypt size %lu using %s", (unsigned long)size, etype_name); wrapped_size = krb5_get_wrapped_length(context, crypto, size); if (wrapped_size != data.length) krb5_errx(context, 1, "calculated wrapped length %lu != " "real wrapped length %lu for data length %lu using " "enctype %s", (unsigned long)wrapped_size, (unsigned long)data.length, (unsigned long)size, etype_name); krb5_data_free(&data); } free(etype_name); free(buf); krb5_crypto_destroy(context, crypto); krb5_free_keyblock_contents(context, &key); }
krb5_error_code _gsskrb5cfx_wrap_length_cfx(krb5_context context, krb5_crypto crypto, int conf_req_flag, int dce_style, 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); if (dce_style) { ret = krb5_crypto_getblocksize(context, crypto, &padsize); } else { 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; }
OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, const gsskrb5_ctx ctx, krb5_context context, int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size, OM_uint32 *max_input_size) { krb5_error_code ret; *max_input_size = 0; /* 16-byte header is always first */ if (req_output_size < 16) return 0; req_output_size -= 16; if (conf_req_flag) { size_t wrapped_size, sz; wrapped_size = req_output_size + 1; do { wrapped_size--; sz = krb5_get_wrapped_length(context, ctx->crypto, wrapped_size); } while (wrapped_size && sz > req_output_size); if (wrapped_size == 0) return 0; /* inner header */ if (wrapped_size < 16) return 0; wrapped_size -= 16; *max_input_size = wrapped_size; } else { krb5_cksumtype type; size_t cksumsize; ret = krb5_crypto_get_checksum_type(context, ctx->crypto, &type); if (ret) return ret; ret = krb5_checksumsize(context, type, &cksumsize); if (ret) return ret; if (req_output_size < cksumsize) return 0; /* Checksum is concatenated with data */ *max_input_size = req_output_size - cksumsize; } return 0; }