Example #1
0
krb5_error_code
krb5int_generate_and_save_subkey(krb5_context context,
                                 krb5_auth_context auth_context,
                                 krb5_keyblock *keyblock,
                                 krb5_enctype enctype)
{
    /* Provide some more fodder for random number code.
       This isn't strong cryptographically; the point here is not
       to guarantee randomness, but to make it less likely that multiple
       sessions could pick the same subkey.  */
    struct {
        krb5_int32 sec, usec;
    } rnd_data;
    krb5_data d;
    krb5_error_code retval;
    krb5_keyblock *kb = NULL;

    if (krb5_crypto_us_timeofday(&rnd_data.sec, &rnd_data.usec) == 0) {
        d.length = sizeof(rnd_data);
        d.data = (char *) &rnd_data;
        krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TIMING, &d);
    }

    retval = krb5_generate_subkey_extended(context, keyblock, enctype, &kb);
    if (retval)
        return retval;
    retval = krb5_auth_con_setsendsubkey(context, auth_context, kb);
    if (retval)
        goto cleanup;
    retval = krb5_auth_con_setrecvsubkey(context, auth_context, kb);
    if (retval)
        goto cleanup;

cleanup:
    if (retval) {
        (void) krb5_auth_con_setsendsubkey(context, auth_context, NULL);
        (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL);
    }
    krb5_free_keyblock(context, kb);
    return retval;
}
Example #2
0
krb5_error_code KRB5_CALLCONV
krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
            const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
    krb5_error_code       retval;
    krb5_ap_rep          *reply = NULL;
    krb5_ap_rep_enc_part *enc = NULL;
    krb5_data             scratch;

    *repl = NULL;

    if (!krb5_is_ap_rep(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;

    /* Decode inbuf. */
    retval = decode_krb5_ap_rep(inbuf, &reply);
    if (retval)
        return retval;

    /* Put together an eblock for this encryption. */
    scratch.length = reply->enc_part.ciphertext.length;
    scratch.data = malloc(scratch.length);
    if (scratch.data == NULL) {
        retval = ENOMEM;
        goto clean_scratch;
    }

    retval = krb5_k_decrypt(context, auth_context->key,
                            KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
                            &reply->enc_part, &scratch);
    if (retval)
        goto clean_scratch;

    /* Now decode the decrypted stuff. */
    retval = decode_krb5_ap_rep_enc_part(&scratch, &enc);
    if (retval)
        goto clean_scratch;

    /* Check reply fields. */
    if ((enc->ctime != auth_context->authentp->ctime)
        || (enc->cusec != auth_context->authentp->cusec)) {
        retval = KRB5_MUTUAL_FAILED;
        goto clean_scratch;
    }

    /* Set auth subkey. */
    if (enc->subkey) {
        retval = krb5_auth_con_setrecvsubkey(context, auth_context,
                                             enc->subkey);
        if (retval)
            goto clean_scratch;
        retval = krb5_auth_con_setsendsubkey(context, auth_context,
                                             enc->subkey);
        if (retval) {
            (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL);
            goto clean_scratch;
        }
        /* Not used for anything yet. */
        auth_context->negotiated_etype = enc->subkey->enctype;
    }

    /* Get remote sequence number. */
    auth_context->remote_seq_number = enc->seq_number;

    TRACE_RD_REP(context, enc->ctime, enc->cusec, enc->subkey,
                 enc->seq_number);

    *repl = enc;
    enc = NULL;

clean_scratch:
    if (scratch.data)
        memset(scratch.data, 0, scratch.length);
    free(scratch.data);
    krb5_free_ap_rep(context, reply);
    krb5_free_ap_rep_enc_part(context, enc);
    return retval;
}