static int krb_enc_iov(krb5_context context, krb5_crypto crypto, unsigned usage, krb5_data *cipher, krb5_data *clear) { krb5_crypto_iov iov[3]; int ret; char *p; size_t len; p = cipher->data; len = cipher->length; iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); iov[0].data.data = emalloc(iov[0].data.length); memcpy(iov[0].data.data, p, iov[0].data.length); p += iov[0].data.length; len -= iov[0].data.length; iov[1].flags = KRB5_CRYPTO_TYPE_TRAILER; krb5_crypto_length(context, crypto, iov[1].flags, &iov[1].data.length); iov[1].data.data = emalloc(iov[1].data.length); memcpy(iov[1].data.data, p + len - iov[1].data.length, iov[1].data.length); len -= iov[1].data.length; iov[2].flags = KRB5_CRYPTO_TYPE_DATA; iov[2].data.length = len; iov[2].data.data = emalloc(len); memcpy(iov[2].data.data, p, len); ret = krb5_decrypt_iov_ivec(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb_enc_iov decrypt iov failed: %d", ret); if (clear->length != iov[2].data.length) errx(1, "length incorrect"); p = clear->data; if (memcmp(iov[2].data.data, p, iov[2].data.length) != 0) errx(1, "iov[2] incorrect"); free(iov[0].data.data); free(iov[1].data.data); free(iov[2].data.data); return 0; }
static int krb_checksum_iov(krb5_context context, krb5_crypto crypto, unsigned usage, krb5_data *plain) { krb5_crypto_iov iov[4]; int ret; char *p; size_t len; p = plain->data; len = plain->length; iov[0].flags = KRB5_CRYPTO_TYPE_CHECKSUM; krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); iov[0].data.data = emalloc(iov[0].data.length); iov[1].flags = KRB5_CRYPTO_TYPE_DATA; iov[1].data.length = len; iov[1].data.data = p; iov[2].flags = KRB5_CRYPTO_TYPE_TRAILER; krb5_crypto_length(context, crypto, iov[0].flags, &iov[2].data.length); iov[2].data.data = malloc(iov[2].data.length); ret = krb5_create_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_create_checksum_iov failed"); ret = krb5_verify_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_verify_checksum_iov"); free(iov[0].data.data); free(iov[2].data.data); return 0; }
static int iov_test(krb5_context context) { krb5_enctype enctype = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96; krb5_error_code ret; krb5_crypto crypto; krb5_keyblock key; krb5_data signonly, in, in2; krb5_crypto_iov iov[6]; size_t len, i; unsigned char *base, *p; ret = krb5_generate_random_keyblock(context, enctype, &key); if (ret) krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); ret = krb5_crypto_init(context, &key, 0, &crypto); if (ret) krb5_err(context, 1, ret, "krb5_crypto_init"); ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len); if (ret) krb5_err(context, 1, ret, "krb5_crypto_length"); signonly.data = "This should be signed"; signonly.length = strlen(signonly.data); in.data = "inputdata"; in.length = strlen(in.data); in2.data = "INPUTDATA"; in2.length = strlen(in2.data); memset(iov, 0, sizeof(iov)); iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; iov[1].flags = KRB5_CRYPTO_TYPE_DATA; iov[1].data = in; iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; iov[2].data = signonly; iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY; iov[4].flags = KRB5_CRYPTO_TYPE_PADDING; iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER; ret = krb5_crypto_length_iov(context, crypto, iov, sizeof(iov)/sizeof(iov[0])); if (ret) krb5_err(context, 1, ret, "krb5_crypto_length_iov"); for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; len += iov[i].data.length; } base = emalloc(len); /* * Allocate data for the fields */ for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue;; iov[i].data.data = p; p += iov[i].data.length; } assert(iov[1].data.length == in.length); memcpy(iov[1].data.data, in.data, iov[1].data.length); /* * Encrypt */ ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); /* * Decrypt */ ret = krb5_decrypt_iov_ivec(context, crypto, 7, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); /* * Verify data */ if (krb5_data_cmp(&iov[1].data, &in) != 0) krb5_errx(context, 1, "decrypted data not same"); /* * Free memory */ free(base); /* Set up for second try */ iov[3].flags = KRB5_CRYPTO_TYPE_DATA; iov[3].data = in; ret = krb5_crypto_length_iov(context, crypto, iov, sizeof(iov)/sizeof(iov[0])); if (ret) krb5_err(context, 1, ret, "krb5_crypto_length_iov"); for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; len += iov[i].data.length; } base = emalloc(len); /* * Allocate data for the fields */ for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue;; iov[i].data.data = p; p += iov[i].data.length; } assert(iov[1].data.length == in.length); memcpy(iov[1].data.data, in.data, iov[1].data.length); assert(iov[3].data.length == in2.length); memcpy(iov[3].data.data, in2.data, iov[3].data.length); /* * Encrypt */ ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec"); /* * Decrypt */ ret = krb5_decrypt_iov_ivec(context, crypto, 7, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec"); /* * Verify data */ if (krb5_data_cmp(&iov[1].data, &in) != 0) krb5_errx(context, 1, "decrypted data 2.1 not same"); if (krb5_data_cmp(&iov[3].data, &in2) != 0) krb5_errx(context, 1, "decrypted data 2.2 not same"); /* * Free memory */ free(base); krb5_crypto_destroy(context, crypto); krb5_free_keyblock_contents(context, &key); return 0; }
static int krb_enc_iov2(krb5_context context, krb5_crypto crypto, unsigned usage, size_t cipher_len, krb5_data *clear) { krb5_crypto_iov iov[4]; krb5_data decrypt; int ret; char *p, *q; size_t len, i; p = clear->data; len = clear->length; iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length); iov[0].data.data = emalloc(iov[0].data.length); iov[1].flags = KRB5_CRYPTO_TYPE_DATA; iov[1].data.length = len; iov[1].data.data = emalloc(iov[1].data.length); memcpy(iov[1].data.data, p, iov[1].data.length); /* padding buffer */ iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_PADDING, &iov[2].data.length); iov[2].data.data = emalloc(iov[2].data.length); iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; krb5_crypto_length(context, crypto, iov[3].flags, &iov[3].data.length); iov[3].data.data = emalloc(iov[3].data.length); ret = krb5_encrypt_iov_ivec(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); if (ret) errx(1, "encrypt iov failed: %d", ret); /* check len */ for (i = 0, len = 0; i < sizeof(iov)/sizeof(iov[0]); i++) len += iov[i].data.length; if (len != cipher_len) errx(1, "cipher len wrong"); /* * Plain decrypt */ p = q = emalloc(len); for (i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) { memcpy(q, iov[i].data.data, iov[i].data.length); q += iov[i].data.length; } ret = krb5_decrypt(context, crypto, usage, p, len, &decrypt); if (ret) krb5_err(context, 1, ret, "krb5_decrypt"); else krb5_data_free(&decrypt); free(p); /* * Now decrypt use iov */ /* padding turn into data */ p = q = emalloc(iov[1].data.length + iov[2].data.length); memcpy(q, iov[1].data.data, iov[1].data.length); q += iov[1].data.length; memcpy(q, iov[2].data.data, iov[2].data.length); free(iov[1].data.data); free(iov[2].data.data); iov[1].data.data = p; iov[1].data.length += iov[2].data.length; iov[2].flags = KRB5_CRYPTO_TYPE_EMPTY; iov[2].data.length = 0; ret = krb5_decrypt_iov_ivec(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL); free(iov[0].data.data); free(iov[3].data.data); if (ret) krb5_err(context, 1, ret, "decrypt iov failed: %d", ret); if (clear->length != iov[1].data.length) errx(1, "length incorrect"); p = clear->data; if (memcmp(iov[1].data.data, p, iov[1].data.length) != 0) errx(1, "iov[1] incorrect"); free(iov[1].data.data); return 0; }
OM_uint32 _gssapi_wrap_cfx_iov(OM_uint32 *minor_status, gsskrb5_ctx ctx, krb5_context context, int conf_req_flag, int *conf_state, gss_iov_buffer_desc *iov, int iov_count) { OM_uint32 major_status, junk; gss_iov_buffer_desc *header, *trailer, *padding; size_t gsshsize, k5hsize; size_t gsstsize, k5tsize; size_t rrc = 0, ec = 0; int i; gss_cfx_wrap_token token; krb5_error_code ret; int32_t seq_number; unsigned usage; krb5_crypto_iov *data = NULL; header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); if (header == NULL) { *minor_status = EINVAL; return GSS_S_FAILURE; } padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); if (padding != NULL) { padding->buffer.length = 0; } trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); if (major_status != GSS_S_COMPLETE) { return major_status; } if (conf_req_flag) { size_t k5psize = 0; size_t k5pbase = 0; size_t k5bsize = 0; size_t size = 0; for (i = 0; i < iov_count; i++) { switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { case GSS_IOV_BUFFER_TYPE_DATA: size += iov[i].buffer.length; break; default: break; } } size += sizeof(gss_cfx_wrap_token_desc); *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize); if (*minor_status) return GSS_S_FAILURE; *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize); if (*minor_status) return GSS_S_FAILURE; *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_PADDING, &k5pbase); if (*minor_status) return GSS_S_FAILURE; if (k5pbase > 1) { k5psize = k5pbase - (size % k5pbase); } else { k5psize = 0; } if (k5psize == 0 && IS_DCE_STYLE(ctx)) { *minor_status = krb5_crypto_getblocksize(context, ctx->crypto, &k5bsize); if (*minor_status) return GSS_S_FAILURE; ec = k5bsize; } else { ec = k5psize; } gsshsize = sizeof(gss_cfx_wrap_token_desc) + k5hsize; gsstsize = sizeof(gss_cfx_wrap_token_desc) + ec + k5tsize; } else { if (IS_DCE_STYLE(ctx)) { *minor_status = EINVAL; return GSS_S_FAILURE; } k5hsize = 0; *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_CHECKSUM, &k5tsize); if (*minor_status) return GSS_S_FAILURE; gsshsize = sizeof(gss_cfx_wrap_token_desc); gsstsize = k5tsize; } /* * */ if (trailer == NULL) { rrc = gsstsize; if (IS_DCE_STYLE(ctx)) rrc -= ec; gsshsize += gsstsize; gsstsize = 0; } else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { major_status = _gk_allocate_buffer(minor_status, trailer, gsstsize); if (major_status) goto failure; } else if (trailer->buffer.length < gsstsize) { *minor_status = KRB5_BAD_MSIZE; major_status = GSS_S_FAILURE; goto failure; } else trailer->buffer.length = gsstsize; /* * */ if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { major_status = _gk_allocate_buffer(minor_status, header, gsshsize); if (major_status != GSS_S_COMPLETE) goto failure; } else if (header->buffer.length < gsshsize) { *minor_status = KRB5_BAD_MSIZE; major_status = GSS_S_FAILURE; goto failure; } else header->buffer.length = gsshsize; token = (gss_cfx_wrap_token)header->buffer.value; token->TOK_ID[0] = 0x05; token->TOK_ID[1] = 0x04; token->Flags = 0; token->Filler = 0xFF; if ((ctx->more_flags & LOCAL) == 0) token->Flags |= CFXSentByAcceptor; if (ctx->more_flags & ACCEPTOR_SUBKEY) token->Flags |= CFXAcceptorSubkey; if (ctx->more_flags & LOCAL) usage = KRB5_KU_USAGE_INITIATOR_SEAL; else usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; 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] = (ec >> 8) & 0xFF; token->EC[1] = (ec >> 0) & 0xFF; } else {