/* * Marshal a KRB-PRIV message into der_out, encrypted with key. Store the * ciphertext in enc_out. Use the timestamp and sequence number from rdata and * the addresses from local_addr and remote_addr (the second of which may be * NULL). der_out and enc_out should be freed by the caller when finished. */ static krb5_error_code create_krbpriv(krb5_context context, const krb5_data *userdata, krb5_key key, const krb5_replay_data *rdata, krb5_address *local_addr, krb5_address *remote_addr, krb5_data *cstate, krb5_data *der_out, krb5_enc_data *enc_out) { krb5_enctype enctype = krb5_k_key_enctype(context, key); krb5_error_code ret; krb5_priv privmsg; krb5_priv_enc_part encpart; krb5_data *der_encpart = NULL, *der_krbpriv; size_t enclen; memset(&privmsg, 0, sizeof(privmsg)); privmsg.enc_part.kvno = 0; privmsg.enc_part.enctype = enctype; encpart.user_data = *userdata; encpart.s_address = local_addr; encpart.r_address = remote_addr; encpart.timestamp = rdata->timestamp; encpart.usec = rdata->usec; encpart.seq_number = rdata->seq; /* Start by encoding the to-be-encrypted part of the message. */ ret = encode_krb5_enc_priv_part(&encpart, &der_encpart); if (ret) return ret; /* put together an eblock for this encryption */ ret = krb5_c_encrypt_length(context, enctype, der_encpart->length, &enclen); if (ret) goto cleanup; ret = alloc_data(&privmsg.enc_part.ciphertext, enclen); if (ret) goto cleanup; ret = krb5_k_encrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART, (cstate->length > 0) ? cstate : NULL, der_encpart, &privmsg.enc_part); if (ret) goto cleanup; ret = encode_krb5_priv(&privmsg, &der_krbpriv); if (ret) goto cleanup; *der_out = *der_krbpriv; free(der_krbpriv); *enc_out = privmsg.enc_part; memset(&privmsg.enc_part, 0, sizeof(privmsg.enc_part)); cleanup: zapfree(privmsg.enc_part.ciphertext.data, privmsg.enc_part.ciphertext.length); zapfreedata(der_encpart); return ret; }
static krb5_error_code mk_priv_basic(krb5_context context, const krb5_data *userdata, krb5_key key, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_data *cstate, krb5_data *outbuf) { krb5_enctype enctype = krb5_k_key_enctype(context, key); krb5_error_code retval; krb5_priv privmsg; krb5_priv_enc_part privmsg_enc_part; krb5_data *scratch1, *scratch2; size_t enclen; privmsg.enc_part.kvno = 0; /* XXX allow user-set? */ privmsg.enc_part.enctype = enctype; privmsg_enc_part.user_data = *userdata; privmsg_enc_part.s_address = local_addr; privmsg_enc_part.r_address = remote_addr; /* We should check too make sure one exists. */ privmsg_enc_part.timestamp = replaydata->timestamp; privmsg_enc_part.usec = replaydata->usec; privmsg_enc_part.seq_number = replaydata->seq; /* start by encoding to-be-encrypted part of the message */ if ((retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch1))) return retval; /* put together an eblock for this encryption */ if ((retval = krb5_c_encrypt_length(context, enctype, scratch1->length, &enclen))) goto clean_scratch; privmsg.enc_part.ciphertext.length = enclen; if (!(privmsg.enc_part.ciphertext.data = malloc(privmsg.enc_part.ciphertext.length))) { retval = ENOMEM; goto clean_scratch; } if ((retval = krb5_k_encrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART, (cstate->length > 0) ? cstate : NULL, scratch1, &privmsg.enc_part))) goto clean_encpart; if ((retval = encode_krb5_priv(&privmsg, &scratch2))) goto clean_encpart; *outbuf = *scratch2; free(scratch2); retval = 0; clean_encpart: memset(privmsg.enc_part.ciphertext.data, 0, privmsg.enc_part.ciphertext.length); free(privmsg.enc_part.ciphertext.data); privmsg.enc_part.ciphertext.length = 0; privmsg.enc_part.ciphertext.data = 0; clean_scratch: memset(scratch1->data, 0, scratch1->length); krb5_free_data(context, scratch1); return retval; }