Esempio n. 1
0
File: mk_priv.c Progetto: krb5/krb5
/*
 * 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;
}
Esempio n. 2
0
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;
}