示例#1
0
static int ntlm2_makechal(krb5_context context, struct kcrap_chal_req_data *req,
                          krb5_data *chal, int *errnum, krb5_data *error_data)
{
	int retval;

	chal->length = 8;
	chal->data = malloc(chal->length);

	if (chal->data == 0) {
		perror("malloc");
		*errnum = errno;
		error_data->data = strdup(error_message(errno));
		error_data->length = strlen(error_data->data);
		return errno;
	} else {
		if ((retval = krb5_c_random_make_octets(context, chal))) {
			*errnum = retval;
			error_data->data = strdup(error_message(retval));
			error_data->length = strlen(error_data->data);
			free(chal->data);
			return retval;
		}
	}

	*errnum = 0;
	return 0;
}
示例#2
0
文件: main.c 项目: DirectXMan12/krb5
static krb5_error_code
nonce_generate(krb5_context ctx, unsigned int length, krb5_data *nonce_out)
{
    krb5_data nonce;
    krb5_error_code retval;
    krb5_timestamp now;

    retval = krb5_timeofday(ctx, &now);
    if (retval != 0)
        return retval;

    retval = alloc_data(&nonce, sizeof(now) + length);
    if (retval != 0)
        return retval;

    retval = krb5_c_random_make_octets(ctx, &nonce);
    if (retval != 0) {
        free(nonce.data);
        return retval;
    }

    store_32_be(now, nonce.data);
    *nonce_out = nonce;
    return 0;
}
示例#3
0
文件: cc_memory.c 项目: NiChrome/krb5
krb5_error_code
krb5int_random_string (krb5_context context, char *string, unsigned int length)
{
    static const unsigned char charlist[] =
        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    krb5_error_code err = 0;
    unsigned char *bytes = NULL;
    unsigned int bytecount = length - 1;

    if (!err) {
        bytes = malloc (bytecount);
        if (bytes == NULL) { err = ENOMEM; }
    }

    if (!err) {
        krb5_data data;
        data.length = bytecount;
        data.data = (char *) bytes;
        err = krb5_c_random_make_octets (context, &data);
    }

    if (!err) {
        unsigned int i;
        for (i = 0; i < bytecount; i++) {
            string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)];
        }
        string[length - 1] = '\0';
    }

    if (bytes != NULL) { free (bytes); }

    return err;
}
示例#4
0
static krb5_error_code ipa_get_random_salt(krb5_context krbctx,
                                           krb5_data *salt)
{
    krb5_error_code kerr;
    int i, v;

    /* make random salt */
    salt->length = KRB5P_SALT_SIZE;
    salt->data = malloc(KRB5P_SALT_SIZE);
    if (!salt->data) {
        return ENOMEM;
    }
    kerr = krb5_c_random_make_octets(krbctx, salt);
    if (kerr) {
        return kerr;
    }

    /* Windows treats the salt as a string.
     * To avoid any compatibility issue, limits octects only to
     * the ASCII printable range, or 0x20 <= val <= 0x7E */
    for (i = 0; i < salt->length; i++) {
        v = (unsigned char)salt->data[i];
        v %= 0x5E; /* 7E - 20 */
        v += 0x20; /* add base */
        salt->data[i] = v;
    }

    return 0;
}
示例#5
0
krb5_error_code KRB5_CALLCONV
krb5_random_confounder(size_t size, krb5_pointer ptr)
{
    krb5_data random_data;

    random_data.length = size;
    random_data.data = ptr;

    return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
}
示例#6
0
文件: dk_cmac.c 项目: Brainiarc7/pbis
krb5_error_code
krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
			krb5_keyusage usage, const krb5_data *ivec,
			krb5_crypto_iov *data, size_t num_data)
{
    const struct krb5_enc_provider *enc = ktp->enc;
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer, *padding;
    krb5_data cksum = empty_data();
    krb5_key ke = NULL, ki = NULL;

    /* E(Confounder | Plaintext | Pad) | Checksum */

    /* Validate header and trailer lengths, and zero out padding length. */
    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL || header->data.length < enc->block_size)
        return KRB5_BAD_MSIZE;
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer == NULL || trailer->data.length < enc->block_size)
        return KRB5_BAD_MSIZE;
    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    if (padding != NULL)
	padding->data.length = 0;

    /* Derive the encryption and integrity keys. */
    ret = derive_keys(enc, key, usage, &ke, &ki);
    if (ret != 0)
        goto cleanup;

    /* Generate confounder. */
    header->data.length = enc->block_size;
    ret = krb5_c_random_make_octets(NULL, &header->data);
    if (ret != 0)
        goto cleanup;

    /* Checksum the plaintext. */
    ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data);
    if (ret != 0)
        goto cleanup;

    /* Encrypt the plaintext (header | data | padding) */
    ret = enc->encrypt(ke, ivec, data, num_data);
    if (ret != 0)
        goto cleanup;

cleanup:
    krb5_k_free_key(NULL, ke);
    krb5_k_free_key(NULL, ki);
    zapfree(cksum.data, cksum.length);
    return ret;
}
示例#7
0
文件: cc_memory.c 项目: krb5/krb5
/* Ensure that mcc_hashtab is initialized.  Call with krb5int_mcc_mutex
 * locked. */
static krb5_error_code
init_table(krb5_context context)
{
    krb5_error_code ret;
    uint8_t seed[K5_HASH_SEED_LEN];
    krb5_data d = make_data(seed, sizeof(seed));

    if (mcc_hashtab != NULL)
        return 0;
    ret = krb5_c_random_make_octets(context, &d);
    if (ret)
        return ret;
    return k5_hashtab_create(seed, 64, &mcc_hashtab);
}
示例#8
0
krb5_error_code
kg_make_confounder(krb5_context context, krb5_enctype enctype,
                   unsigned char *buf)
{
    int confsize;
    krb5_data lrandom;

    confsize = kg_confounder_size(context, enctype);
    if (confsize < 0)
        return KRB5_BAD_MSIZE;

    lrandom.length = confsize;
    lrandom.data = (char *)buf;

    return(krb5_c_random_make_octets(context, &lrandom));
}
示例#9
0
krb5_error_code
krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp,
                            krb5_key key, krb5_keyusage usage,
                            const krb5_crypto_iov *data, size_t num_data,
                            krb5_data *output)
{
    krb5_error_code ret;
    krb5_data conf, hashval;
    krb5_key xorkey = NULL;
    krb5_crypto_iov *hash_iov, iov;
    size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;

    /* Partition the output buffer into confounder and hash. */
    conf = make_data(output->data, blocksize);
    hashval = make_data(output->data + blocksize, hashsize);

    /* Create the confounder. */
    ret = krb5_c_random_make_octets(NULL, &conf);
    if (ret != 0)
        return ret;

    ret = mk_xorkey(key, &xorkey);
    if (ret)
        return ret;

    /* Hash the confounder, then the input data. */
    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
    if (hash_iov == NULL)
        goto cleanup;
    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
    hash_iov[0].data = conf;
    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
    ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
    if (ret != 0)
        goto cleanup;

    /* Confounder and hash are in output buffer; encrypt them in place. */
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
    iov.data = *output;
    ret = ctp->enc->encrypt(xorkey, NULL, &iov, 1);

cleanup:
    free(hash_iov);
    krb5_k_free_key(NULL, xorkey);
    return ret;
}
示例#10
0
krb5_error_code
krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui_4 *seqno)
{
    krb5_data seed;
    krb5_error_code retval;
#if 0
/* 
 * Solaris Kerberos:  Don't bother with this PRNG stuff,
 * we have /dev/random and PKCS#11 to handle Random Numbers.
 */


    seed.length = key->length;
    seed.data = key->contents;
    if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
	return(retval);
#endif /* 0 */

    seed.length = sizeof(*seqno);
    seed.data = (char *) seqno;
    retval = krb5_c_random_make_octets(context, &seed);
    if (retval)
	return retval;
    /*
     * Work around implementation incompatibilities by not generating
     * initial sequence numbers greater than 2^30.  Previous MIT
     * implementations use signed sequence numbers, so initial
     * sequence numbers 2^31 to 2^32-1 inclusive will be rejected.
     * Letting the maximum initial sequence number be 2^30-1 allows
     * for about 2^30 messages to be sent before wrapping into
     * "negative" numbers.
     */
    *seqno &= 0x3fffffff;
    if (*seqno == 0)
	*seqno = 1;
    return 0;
}
示例#11
0
krb5_error_code
verify_securid_data_2(krb5_context context, krb5_db_entry *client,
                      krb5_sam_response_2 *sr2,
                      krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa,
                      krb5_sam_challenge_2 **sc2_out)
{
    krb5_error_code retval;
    int new_pin = 0;
    krb5_key_data *client_key_data = NULL;
    krb5_keyblock client_key;
    krb5_data scratch;
    krb5_enc_sam_response_enc_2 *esre2 = NULL;
    struct securid_track_data sid_track_data, *trackp = NULL;
    krb5_data tmp_data;
    SDI_HANDLE sd_handle = SDI_HANDLE_NONE;
    krb5_sam_challenge_2 *sc2p = NULL;
    char *cp, *user = NULL;
    char *securid_user = NULL;
    char passcode[LENPRNST+1];
    char max_pin_len, min_pin_len, alpha_pin;

    memset(&client_key, 0, sizeof(client_key));
    memset(&scratch, 0, sizeof(scratch));
    *sc2_out = NULL;

    retval = krb5_unparse_name(context, client->princ, &user);
    if (retval != 0) {
        com_err("krb5kdc", retval,
                "while unparsing client name in verify_securid_data_2");
        return retval;
    }

    if ((sr2->sam_enc_nonce_or_sad.ciphertext.data == NULL) ||
        (sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) {
          retval = KRB5KDC_ERR_PREAUTH_FAILED;
          krb5_set_error_message(context, retval,
                                 "No preauth data supplied in "
                                 "verify_securid_data_2 (%s)", user);
          goto cleanup;
    }

    retval = krb5_dbe_find_enctype(context, client,
                                   sr2->sam_enc_nonce_or_sad.enctype,
                                   KRB5_KDB_SALTTYPE_NORMAL,
                                   sr2->sam_enc_nonce_or_sad.kvno,
                                   &client_key_data);
    if (retval) {
        com_err("krb5kdc", retval,
                "while getting client key in verify_securid_data_2 (%s)",
                user);
        goto cleanup;
    }

    retval = krb5_dbe_decrypt_key_data(context, NULL, client_key_data,
                                       &client_key, NULL);
    if (retval != 0) {
        com_err("krb5kdc", retval,
                "while decrypting client key in verify_securid_data_2 (%s)",
                user);
        goto cleanup;
    }

    scratch.length = sr2->sam_enc_nonce_or_sad.ciphertext.length;
    scratch.data = k5alloc(scratch.length, &retval);
    if (retval)
        goto cleanup;
    retval = krb5_c_decrypt(context, &client_key,
                            KRB5_KEYUSAGE_PA_SAM_RESPONSE, 0,
                            &sr2->sam_enc_nonce_or_sad, &scratch);
    if (retval) {
        com_err("krb5kdc", retval,
                "while decrypting SAD in verify_securid_data_2 (%s)", user);
        goto cleanup;
    }

    retval = decode_krb5_enc_sam_response_enc_2(&scratch, &esre2);
    if (retval) {
        com_err("krb5kdc", retval,
                "while decoding SAD in verify_securid_data_2 (%s)", user);
        esre2 = NULL;
        goto cleanup;
    }

    if (sr2->sam_nonce != esre2->sam_nonce) {
        com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
                "while checking nonce in verify_securid_data_2 (%s)", user);
        retval = KRB5KDC_ERR_PREAUTH_FAILED;
        goto cleanup;
    }

    if (esre2->sam_sad.length == 0 || esre2->sam_sad.data == NULL) {
        com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
                "No SecurID passcode in verify_securid_data_2 (%s)", user);
        retval = KRB5KDC_ERR_PREAUTH_FAILED;
        goto cleanup;
    }

    /* Copy out SAD to null-terminated buffer */
    memset(passcode, 0, sizeof(passcode));
    if (esre2->sam_sad.length > (sizeof(passcode) - 1)) {
        retval = KRB5KDC_ERR_PREAUTH_FAILED;
        com_err("krb5kdc", retval,
                "SecurID passcode/PIN too long (%d bytes) in "
                "verify_securid_data_2 (%s)",
                esre2->sam_sad.length, user);
        goto cleanup;
    }
    memcpy(passcode, esre2->sam_sad.data, esre2->sam_sad.length);

    securid_user = strdup(user);
    if (!securid_user) {
        retval = ENOMEM;
        com_err("krb5kdc", ENOMEM,
                "while copying user name in verify_securid_data_2 (%s)", user);
        goto cleanup;
    }
    cp = strchr(securid_user, '@');
    if (cp != NULL)
        *cp = '\0';

    /* Check for any track_id data that may have state from a previous attempt
     * at SecurID authentication. */

    if (sr2->sam_track_id.data && (sr2->sam_track_id.length > 0)) {
        krb5_data track_id_data;

        memset(&track_id_data, 0, sizeof(track_id_data));
        retval = securid_decrypt_track_data_2(context, client,
                                              &sr2->sam_track_id,
                                              &track_id_data);
        if (retval) {
            com_err("krb5kdc", retval,
                    "while decrypting SecurID trackID in "
                    "verify_securid_data_2 (%s)", user);
           goto cleanup;
        }
        if (track_id_data.length < sizeof (struct securid_track_data)) {
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            com_err("krb5kdc", retval, "Length of track data incorrect");
            goto cleanup;
        }
        trackp = (struct securid_track_data *)track_id_data.data;

        if(trackp->hostid != gethostid()) {
            krb5_klog_syslog(LOG_INFO, "Unexpected challenge response");
            retval = KRB5KDC_ERR_DISCARD;
            goto cleanup;
        }

        switch(trackp->state) {
        case SECURID_STATE_INITIAL:
            goto initial;
            break;
        case SECURID_STATE_NEW_PIN_AGAIN:
        {
            int pin1_len, pin2_len;

            trackp->handle = ntohl(trackp->handle);
            pin2_len = strlen(passcode);
            pin1_len = strlen(trackp->passcode);

            if ((pin1_len != pin2_len) ||
                (memcmp(passcode, trackp->passcode, pin1_len) != 0)) {
                retval = KRB5KDC_ERR_PREAUTH_FAILED;
                krb5_klog_syslog(LOG_INFO, "New SecurID PIN Failed for user "
                                 "%s: PIN mis-match", user);
                break;
            }
            retval = SD_Pin(trackp->handle, passcode);
            SD_Close(trackp->handle);
            if (retval == ACM_NEW_PIN_ACCEPTED) {
                enc_tkt_reply->flags|=  TKT_FLG_HW_AUTH;
                enc_tkt_reply->flags|=  TKT_FLG_PRE_AUTH;
                krb5_klog_syslog(LOG_INFO, "SecurID PIN Accepted for %s in "
                                 "verify_securid_data_2",
                                 securid_user);
                retval = 0;
            } else {
                retval = KRB5KDC_ERR_PREAUTH_FAILED;
                krb5_klog_syslog(LOG_INFO,
                                 "SecurID PIN Failed for user %s (AceServer "
                                 "returns %d) in verify_securid_data_2",
                                 user, retval);
            }
            break;
        }
        case SECURID_STATE_NEW_PIN: {
            krb5_sam_challenge_2_body sc2b;
            sc2p = k5alloc(sizeof *sc2p, &retval);
            if (retval)
                goto cleanup;
            memset(sc2p, 0, sizeof(*sc2p));
            memset(&sc2b, 0, sizeof(sc2b));
            sc2b.sam_type = PA_SAM_TYPE_SECURID;
            sc2b.sam_response_prompt.data = NEW_PIN_AGAIN_message;
            sc2b.sam_response_prompt.length =
                strlen(sc2b.sam_response_prompt.data);
            sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
            sc2b.sam_etype = client_key.enctype;

            tmp_data.data = (char *)&sc2b.sam_nonce;
            tmp_data.length = sizeof(sc2b.sam_nonce);
            if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
                com_err("krb5kdc", retval,
                        "while making nonce for SecurID new "
                        "PIN2 SAM_CHALLENGE_2 (%s)", user);
                goto cleanup;
            }
            sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN;
            sid_track_data.handle = trackp->handle;
            sid_track_data.hostid = gethostid();
            /* Should we complain if sizes don't work ??  */
            memcpy(sid_track_data.passcode, passcode,
                   sizeof(sid_track_data.passcode));
            tmp_data.data = (char *)&sid_track_data;
            tmp_data.length = sizeof(sid_track_data);
            if ((retval = securid_encrypt_track_data_2(context, client,
                                                       &tmp_data,
                                                       &sc2b.sam_track_id))) {
                com_err("krb5kdc", retval,
                        "while encrypting NEW PIN2 SecurID "
                        "track data for SAM_CHALLENGE_2 (%s)",
                        securid_user);
                goto cleanup;
            }
            retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
                                                            &sc2b,
                                                            &client_key);
            if (retval) {
                com_err("krb5kdc", retval,
                        "while making cksum for "
                        "SAM_CHALLENGE_2 (new PIN2) (%s)", securid_user);
                goto cleanup;
            }
            krb5_klog_syslog(LOG_INFO,
                             "Requesting verification of new PIN for user %s",
                             securid_user);
            *sc2_out = sc2p;
            sc2p = NULL;
            /*sc2_out may be set even on error path*/
            retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
            goto cleanup;
        }
        case SECURID_STATE_NEXT_CODE:
            trackp->handle = ntohl(trackp->handle);
            retval = SD_Next(trackp->handle, passcode);
            SD_Close(trackp->handle);
            if (retval == ACM_OK) {
                enc_tkt_reply->flags |=  TKT_FLG_HW_AUTH | TKT_FLG_PRE_AUTH;

                krb5_klog_syslog(LOG_INFO, "Next SecurID Code Accepted for "
                                 "user %s", securid_user);
                retval = 0;
            } else {
                krb5_klog_syslog(LOG_INFO, "Next SecurID Code Failed for user "
                                 "%s (AceServer returns %d) in "
                                 "verify_securid_data_2", user, retval);
                retval = KRB5KDC_ERR_PREAUTH_FAILED;
            }
            break;
        }
    } else {            /* No track data, this is first of N attempts */
    initial:
        retval = SD_Init(&sd_handle);
        if (retval) {
            com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
                    "SD_Init() returns error %d in verify_securid_data_2 (%s)",
                    retval, securid_user);
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            goto cleanup;
        }

        retval = SD_Lock(sd_handle, securid_user);
        if (retval != ACM_OK) {
            SD_Close(sd_handle);
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            krb5_klog_syslog(LOG_INFO,
                             "SD_Lock() failed (AceServer returns %d) for %s",
                             retval, securid_user);
            goto cleanup;
        }

        retval = SD_Check(sd_handle, passcode, securid_user);
        switch (retval) {
        case ACM_OK:
            SD_Close(sd_handle);
            enc_tkt_reply->flags|=  TKT_FLG_HW_AUTH;
            enc_tkt_reply->flags|=  TKT_FLG_PRE_AUTH;
            krb5_klog_syslog(LOG_INFO, "SecurID passcode accepted for user %s",
                             user);
            retval = 0;
            break;
        case ACM_ACCESS_DENIED:
            SD_Close(sd_handle);
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            krb5_klog_syslog(LOG_INFO, "AceServer returns Access Denied for "
                             "user %s (SAM2)", user);
            goto cleanup;
        case ACM_NEW_PIN_REQUIRED:
            new_pin = 1;
            /*fall through*/
        case ACM_NEXT_CODE_REQUIRED: {
            krb5_sam_challenge_2_body sc2b;
            sc2p = k5alloc(sizeof *sc2p, &retval);
            if (retval)
                goto cleanup;

            memset(sc2p, 0, sizeof(*sc2p));
            memset(&sc2b, 0, sizeof(sc2b));

            sc2b.sam_type = PA_SAM_TYPE_SECURID;
            sc2b.sam_response_prompt.data = NEXT_PASSCODE_message;
            sc2b.sam_response_prompt.length =
                strlen(sc2b.sam_response_prompt.data);
            sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
            sc2b.sam_etype = client_key.enctype;
            if (new_pin) {
                if ((AceGetMaxPinLen(sd_handle, &max_pin_len) == ACE_SUCCESS)
                    && (AceGetMinPinLen(sd_handle,
                                        &min_pin_len) == ACE_SUCCESS)
                    && (AceGetAlphanumeric(sd_handle,
                                           &alpha_pin) == ACE_SUCCESS)) {
                    sprintf(PIN_message,
                            "New PIN must contain %d to %d %sdigits",
                            min_pin_len, max_pin_len,
                            (alpha_pin == 0) ? "" : "alphanumeric ");
                    sc2b.sam_challenge_label.data = PIN_message;
                    sc2b.sam_challenge_label.length =
                        strlen(sc2b.sam_challenge_label.data);
                } else {
                    sc2b.sam_challenge_label.length = 0;
                }
            }

            tmp_data.data = (char *)&sc2b.sam_nonce;
            tmp_data.length = sizeof(sc2b.sam_nonce);
            if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
                com_err("krb5kdc", retval,
                        "while making nonce for SecurID SAM_CHALLENGE_2 (%s)",
                        user);
                goto cleanup;
            }
            if (new_pin)
                sid_track_data.state = SECURID_STATE_NEW_PIN;
            else
                sid_track_data.state = SECURID_STATE_NEXT_CODE;
            sid_track_data.handle = htonl(sd_handle);
            sid_track_data.hostid = gethostid();
            tmp_data.data = (char *)&sid_track_data;
            tmp_data.length = sizeof(sid_track_data);
            retval = securid_encrypt_track_data_2(context, client, &tmp_data,
                                                  &sc2b.sam_track_id);
            if (retval) {
                   com_err("krb5kdc", retval,
                           "while encrypting SecurID track "
                           "data for SAM_CHALLENGE_2 (%s)",
                           securid_user);
                   goto cleanup;
            }
            retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
                                                            &sc2b,
                                                            &client_key);
            if (retval) {
                com_err("krb5kdc", retval,
                        "while making cksum for SAM_CHALLENGE_2 (%s)",
                        securid_user);
            }
            if (new_pin)
                krb5_klog_syslog(LOG_INFO, "New SecurID PIN required for "
                                 "user %s", securid_user);
            else
                krb5_klog_syslog(LOG_INFO, "Next SecurID passcode required "
                                 "for user %s", securid_user);
            *sc2_out = sc2p;
            sc2p = NULL;
            retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
            /*sc2_out is permitted as an output on error path*/
            goto cleanup;
        }
        default:
            com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
                    "AceServer returns unknown error code %d "
                    "in verify_securid_data_2\n", retval);
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            goto cleanup;
        }
    }   /* no track_id data */

cleanup:
    krb5_free_keyblock_contents(context, &client_key);
    free(scratch.data);
    krb5_free_enc_sam_response_enc_2(context, esre2);
    free(user);
    free(securid_user);
    free(trackp);
    krb5_free_sam_challenge_2(context, sc2p);
    return retval;
}
示例#12
0
krb5_error_code
get_securid_edata_2(krb5_context context, krb5_db_entry *client,
                    krb5_keyblock *client_key,
                    krb5_sam_challenge_2_body *sc2b, krb5_sam_challenge_2 *sc2)
{
    krb5_error_code retval;
    krb5_data scratch;
    char *user = NULL;
    char *def_user = "******";
    struct securid_track_data sid_track_data;
    krb5_data tmp_data;

    scratch.data = NULL;
    sc2b->sam_track_id.data = NULL;

    retval = krb5_unparse_name(context, client->princ, &user);
    if (retval)
        goto cleanup;

    sc2b->sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
    sc2b->sam_type_name.length = 0;
    sc2b->sam_challenge_label.length = 0;
    sc2b->sam_challenge.length = 0;
    sc2b->sam_response_prompt.data = PASSCODE_message;
    sc2b->sam_response_prompt.length = strlen(sc2b->sam_response_prompt.data);
    sc2b->sam_pk_for_sad.length = 0;
    sc2b->sam_type = PA_SAM_TYPE_SECURID;

    sid_track_data.state = SECURID_STATE_INITIAL;
    sid_track_data.hostid = gethostid();
    tmp_data.data = (char *)&sid_track_data;
    tmp_data.length = sizeof(sid_track_data);
    retval = securid_encrypt_track_data_2(context, client, &tmp_data,
                                          &sc2b->sam_track_id);
    if (retval != 0) {
        com_err("krb5kdc", retval, "while encrypting nonce track data");
        goto cleanup;
    }

    scratch.data = (char *)&sc2b->sam_nonce;
    scratch.length = sizeof(sc2b->sam_nonce);
    retval = krb5_c_random_make_octets(context, &scratch);
    if (retval) {
        com_err("krb5kdc", retval,
                "while generating nonce data in get_securid_edata_2 (%s)",
                user ? user : def_user);
        goto cleanup;
    }

    /* Get the client's key */
    sc2b->sam_etype = client_key->enctype;

    retval = securid_make_sam_challenge_2_and_cksum(context,
                                                    sc2, sc2b, client_key);
    if (retval) {
        com_err("krb5kdc", retval,
                "while making SAM_CHALLENGE_2 checksum (%s)",
                user ? user : def_user);
    }

cleanup:
    free(user);
    if (retval) {
        krb5_free_data_contents(context, &sc2b->sam_track_id);
        sc2b->sam_track_id.data = NULL;
    }
    return retval;
}
示例#13
0
krb5_error_code
krb5int_fast_prep_req(krb5_context context,
                      struct krb5int_fast_request_state *state,
                      krb5_kdc_req *request,
                      const krb5_data *to_be_checksummed,
                      kdc_req_encoder_proc encoder,
                      krb5_data **encoded_request)
{
    krb5_error_code retval = 0;
    krb5_pa_data *pa_array[2];
    krb5_pa_data pa[2];
    krb5_fast_req fast_req;
    krb5_fast_armored_req *armored_req = NULL;
    krb5_data *encoded_fast_req = NULL;
    krb5_data *encoded_armored_req = NULL;
    krb5_data *local_encoded_result = NULL;
    krb5_data random_data;
    char random_buf[4];

    assert(state != NULL);
    assert(state->fast_outer_request.padata == NULL);
    memset(pa_array, 0, sizeof pa_array);
    if (state->armor_key == NULL) {
        return encoder(request, encoded_request);
    }

    TRACE_FAST_ENCODE(context);
    /* Fill in a fresh random nonce for each inner request*/
    random_data.length = 4;
    random_data.data = (char *)random_buf;
    retval = krb5_c_random_make_octets(context, &random_data);
    if (retval == 0) {
        request->nonce = 0x7fffffff & load_32_n(random_buf);
        state->nonce = request->nonce;
    }
    fast_req.req_body =  request;
    if (fast_req.req_body->padata == NULL) {
        fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *));
        if (fast_req.req_body->padata == NULL)
            retval = ENOMEM;
    }
    fast_req.fast_options = state->fast_options;
    if (retval == 0)
        retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req);
    if (retval == 0) {
        armored_req = calloc(1, sizeof(krb5_fast_armored_req));
        if (armored_req == NULL)
            retval = ENOMEM;
    }
    if (retval == 0)
        armored_req->armor = state->armor;
    if (retval ==0)
        retval = krb5_c_make_checksum(context, 0, state->armor_key,
                                      KRB5_KEYUSAGE_FAST_REQ_CHKSUM,
                                      to_be_checksummed,
                                      &armored_req->req_checksum);
    if (retval == 0)
        retval = krb5_encrypt_helper(context, state->armor_key,
                                     KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req,
                                     &armored_req->enc_part);
    if (retval == 0)
        retval = encode_krb5_pa_fx_fast_request(armored_req,
                                                &encoded_armored_req);
    if (retval==0) {
        pa[0].pa_type = KRB5_PADATA_FX_FAST;
        pa[0].contents = (unsigned char *) encoded_armored_req->data;
        pa[0].length = encoded_armored_req->length;
        pa_array[0] = &pa[0];
    }
    state->fast_outer_request.padata = pa_array;
    if(retval == 0)
        retval = encoder(&state->fast_outer_request, &local_encoded_result);
    if (retval == 0) {
        *encoded_request = local_encoded_result;
        local_encoded_result = NULL;
    }
    if (encoded_armored_req)
        krb5_free_data(context, encoded_armored_req);
    if (armored_req) {
        armored_req->armor = NULL; /*owned by state*/
        krb5_free_fast_armored_req(context, armored_req);
    }
    if (encoded_fast_req)
        krb5_free_data(context, encoded_fast_req);
    if (local_encoded_result)
        krb5_free_data(context, local_encoded_result);
    state->fast_outer_request.padata = NULL;
    return retval;
}
示例#14
0
/*ARGSUSED*/
static krb5_error_code
k5_md5des_hash(krb5_context context, krb5_const krb5_keyblock *key,
	       krb5_keyusage usage, const krb5_data *ivec,
	       const krb5_data *input, krb5_data *output)
{
    krb5_error_code ret = 0;
    krb5_data data;
    unsigned char conf[CONFLENGTH];
    krb5_keyblock xorkey;
    int i;
    CK_MECHANISM mechanism;
    CK_RV rv;
    CK_ULONG hashlen = MD5_CKSUM_LENGTH;

    if (key->length != 8)
	return(KRB5_BAD_KEYSIZE);
    if (ivec)
	return(KRB5_CRYPTO_INTERNAL);
    if (output->length != (CONFLENGTH+MD5_CKSUM_LENGTH))
	return(KRB5_CRYPTO_INTERNAL);

    /* create the confouder */

    data.length = CONFLENGTH;
    data.data = (char *) conf;
    if ((ret = krb5_c_random_make_octets(context, &data)))
	return(ret);

    xorkey.magic = key->magic;
    xorkey.enctype = key->enctype;
    xorkey.length = key->length;
    xorkey.contents = (krb5_octet *)malloc(key->length);
    if (xorkey.contents == NULL)
	return(KRB5_CRYPTO_INTERNAL);

    (void) memcpy(xorkey.contents, key->contents, xorkey.length);

    for (i=0; i<xorkey.length; i++)
	xorkey.contents[i] ^= 0xf0;

    if (!mit_des_check_key_parity(xorkey.contents)) {
	ret = KRB5DES_BAD_KEYPAR;
	goto cleanup;
    }

    if (mit_des_is_weak_key(xorkey.contents)) {
	ret = KRB5DES_WEAK_KEY;
	goto cleanup;
    }

    /* hash the confounder, then the input data */
    mechanism.mechanism = CKM_MD5;
    mechanism.pParameter = NULL_PTR;
    mechanism.ulParameterLen = 0;

    if ((rv = C_DigestInit(krb_ctx_hSession(context), &mechanism)) != CKR_OK) {
	KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_md5des_hash: "
	"rv = 0x%x.", rv);
	ret = PKCS_ERR;
	goto cleanup;
    }

    if ((rv = C_DigestUpdate(krb_ctx_hSession(context),
	(CK_BYTE_PTR)conf, (CK_ULONG)sizeof(conf))) != CKR_OK) {
	KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_hash: "
	    "rv = 0x%x", rv);
	ret = PKCS_ERR;
	goto cleanup;
    }

    if ((rv = C_DigestUpdate(krb_ctx_hSession(context),
	(CK_BYTE_PTR)input->data, (CK_ULONG)input->length)) != CKR_OK) {
	KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_hash: "
	    "rv = 0x%x", rv);
	return(PKCS_ERR);
    }

    if ((rv = C_DigestFinal(krb_ctx_hSession(context),
	(CK_BYTE_PTR)(output->data + CONFLENGTH),
	(CK_ULONG_PTR)&hashlen)) != CKR_OK) {
	KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_md5des_hash: "
	    "rv = 0x%x", rv);
	ret = PKCS_ERR;
	goto cleanup;
    }

    /* construct the buffer to be encrypted */

    (void) memcpy(output->data, conf, CONFLENGTH);

    /* encrypt it, in place.  this has a return value, but it's
       always zero.  */

    ret = mit_des_cbc_encrypt(context,
	(krb5_pointer) output->data,
	(krb5_pointer) output->data, output->length,
	&xorkey, (unsigned char*) mit_des_zeroblock, 1);

cleanup:
    free(xorkey.contents);
    return(ret);
}
示例#15
0
static krb5_error_code
krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
			    const struct krb5_enc_provider *enc,
			    const struct krb5_hash_provider *hash,
			    const krb5_keyblock *key,
			    krb5_keyusage usage,
			    const krb5_data *ivec,
			    krb5_crypto_iov *data,
			    size_t num_data)
{
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer;
    krb5_keyblock k1, k2, k3;
    krb5_data d1, d2, d3;
    krb5_data checksum, confounder, header_data;
    krb5_keyusage ms_usage;
    char salt_data[14];
    krb5_data salt;
    size_t i;

    d1.length = d2.length = d3.length = 0;
    d1.data = d2.data = d3.data = NULL;

    /*
     * Caller must have provided space for the header, padding
     * and trailer; per RFC 4757 we will arrange it as:
     *
     *	    Checksum | E(Confounder | Plaintext)
     */

    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL ||
	header->data.length < hash->hashsize + CONFOUNDERLENGTH)
	return KRB5_BAD_MSIZE;

    header_data = header->data;

    /* Trailer may be absent */
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer != NULL)
	trailer->data.length = 0;

    /* Ensure that there is no padding */
    for (i = 0; i < num_data; i++) {
	if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING)
	    data[i].data.length = 0;
    }

    ret = alloc_derived_key(enc, &k1, &d1, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k2, &d2, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k3, &d3, key);
    if (ret != 0)
	goto cleanup;

    /* Begin the encryption, compute K1 */
    salt.data = salt_data;
    salt.length = sizeof(salt_data);

    ms_usage = krb5int_arcfour_translate_usage(usage);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
	strncpy(salt.data, krb5int_arcfour_l40, salt.length);
	store_32_le(ms_usage, salt.data + 10);
    } else {
	salt.length = 4;
	store_32_le(ms_usage, salt.data);
    }
    ret = krb5_hmac(hash, key, 1, &salt, &d1);
    if (ret != 0)
	goto cleanup;

    memcpy(k2.contents, k1.contents, k2.length);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
	memset(k1.contents + 7, 0xAB, 9);

    header->data.length = hash->hashsize + CONFOUNDERLENGTH;

    confounder.data = header->data.data + hash->hashsize;
    confounder.length = CONFOUNDERLENGTH;

    ret = krb5_c_random_make_octets(0, &confounder);
    if (ret != 0)
	goto cleanup;

    checksum.data = header->data.data;
    checksum.length = hash->hashsize;

    /* Adjust pointers so confounder is at start of header */
    header->data.length -= hash->hashsize;
    header->data.data   += hash->hashsize;

    ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum);
    if (ret != 0)
	goto cleanup;

    ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
    if (ret != 0)
	goto cleanup;

    ret = enc->encrypt_iov(&k3, ivec, data, num_data);
    if (ret != 0)
	goto cleanup;

cleanup:
    header->data = header_data; /* restore header pointers */

    if (d1.data != NULL) {
	memset(d1.data, 0, d1.length);
	free(d1.data);
    }
    if (d2.data != NULL) {
	memset(d2.data, 0, d2.length);
	free(d2.data);
    }
    if (d3.data != NULL) {
	memset(d3.data, 0, d3.length);
	free(d3.data);
    }

    return ret;
}
示例#16
0
文件: enc_rc4.c 项目: Akasurde/krb5
krb5_error_code
krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
                        krb5_keyusage usage, const krb5_data *ivec,
                        krb5_crypto_iov *data, size_t num_data)
{
    const struct krb5_enc_provider *enc = ktp->enc;
    const struct krb5_hash_provider *hash = ktp->hash;
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer;
    krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
    krb5_data checksum, confounder, header_data;
    size_t i;

    /*
     * Caller must have provided space for the header, padding
     * and trailer; per RFC 4757 we will arrange it as:
     *
     *      Checksum | E(Confounder | Plaintext)
     */

    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL ||
        header->data.length < hash->hashsize + CONFOUNDERLENGTH)
        return KRB5_BAD_MSIZE;

    header_data = header->data;

    /* Trailer may be absent. */
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer != NULL)
        trailer->data.length = 0;

    /* Ensure that there is no padding. */
    for (i = 0; i < num_data; i++) {
        if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING)
            data[i].data.length = 0;
    }

    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
                                  &usage_keyblock);
    if (ret != 0)
        goto cleanup;
    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
                                  &enc_keyblock);
    if (ret != 0)
        goto cleanup;

    /* Derive a usage key from the session key and usage. */
    ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
    if (ret != 0)
        goto cleanup;

    /* Generate a confounder in the header block, after the checksum. */
    header->data.length = hash->hashsize + CONFOUNDERLENGTH;
    confounder = make_data(header->data.data + hash->hashsize,
                           CONFOUNDERLENGTH);
    ret = krb5_c_random_make_octets(0, &confounder);
    if (ret != 0)
        goto cleanup;
    checksum = make_data(header->data.data, hash->hashsize);

    /* Adjust pointers so confounder is at start of header. */
    header->data.length -= hash->hashsize;
    header->data.data += hash->hashsize;

    /* Compute the checksum using the usage key. */
    ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
                                &checksum);
    if (ret != 0)
        goto cleanup;

    /* Derive the encryption key from the usage key and checksum. */
    ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
    if (ret)
        goto cleanup;

    ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);

cleanup:
    header->data = header_data; /* Restore header pointers. */
    krb5int_c_free_keyblock(NULL, usage_keyblock);
    krb5int_c_free_keyblock(NULL, enc_keyblock);
    return ret;
}
示例#17
0
文件: packet.c 项目: Akasurde/krb5
/* Generate size bytes of random data into the buffer. */
static inline krb5_error_code
randomize(krb5_context ctx, void *buffer, unsigned int size)
{
    krb5_data rdata = make_data(buffer, size);
    return krb5_c_random_make_octets(ctx, &rdata);
}
示例#18
0
krb5_error_code
krb5_old_encrypt(const struct krb5_enc_provider *enc,
		 const struct krb5_hash_provider *hash,
		 const krb5_keyblock *key,
		 krb5_keyusage usage,
		 const krb5_data *ivec,
		 const krb5_data *input,
		 krb5_data *output)
{
    krb5_error_code ret;
    size_t blocksize, hashsize, enclen;
    krb5_data datain, crcivec;
    int real_ivec;

    blocksize = enc->block_size;
    hashsize = hash->hashsize;

    krb5_old_encrypt_length(enc, hash, input->length, &enclen);

    if (output->length < enclen)
	return(KRB5_BAD_MSIZE);

    output->length = enclen;

    /* fill in confounded, padded, plaintext buffer with zero checksum */

    memset(output->data, 0, output->length);

    datain.length = blocksize;
    datain.data = output->data;

    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &datain)))
	return(ret);
    memcpy(output->data+blocksize+hashsize, input->data, input->length);

    /* compute the checksum */

    datain.length = hashsize;
    datain.data = output->data+blocksize;

    if ((ret = ((*(hash->hash))(1, output, &datain))))
	goto cleanup;

    /* encrypt it */

    /* XXX this is gross, but I don't have much choice */
    if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) {
	crcivec.length = key->length;
	crcivec.data = (char *) key->contents;
	ivec = &crcivec;
	real_ivec = 0;
    } else
	real_ivec = 1;

    if ((ret = ((*(enc->encrypt))(key, ivec, output, output))))
	goto cleanup;

    /* update ivec */
    if (real_ivec && ivec != NULL && ivec->length == blocksize)
	memcpy(ivec->data, output->data + output->length - blocksize,
	       blocksize);
cleanup:
    if (ret)
	memset(output->data, 0, output->length);

    return(ret);
}
示例#19
0
static krb5_error_code
k5_md4des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
	       const krb5_data *input, krb5_data *output)
{
    krb5_error_code ret;
    krb5_data data;
    krb5_MD4_CTX ctx;
    unsigned char conf[CONFLENGTH];
    unsigned char xorkey[8];
    unsigned int i;
    mit_des_key_schedule schedule;

    if (key->length != 8)
	return(KRB5_BAD_KEYSIZE);
    if (ivec)
	return(KRB5_CRYPTO_INTERNAL);
    if (output->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH))
	return(KRB5_CRYPTO_INTERNAL);

    /* create the confouder */

    data.length = CONFLENGTH;
    data.data = (char *) conf;
    if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &data)))
	return(ret);

    /* create and schedule the encryption key */

    memcpy(xorkey, key->contents, sizeof(xorkey));
    for (i=0; i<sizeof(xorkey); i++)
	xorkey[i] ^= 0xf0;
    
    switch (ret = mit_des_key_sched(xorkey, schedule)) {
    case -1:
	return(KRB5DES_BAD_KEYPAR);
    case -2:
	return(KRB5DES_WEAK_KEY);
    }

    /* hash the confounder, then the input data */

    krb5_MD4Init(&ctx);
    krb5_MD4Update(&ctx, conf, CONFLENGTH);
    krb5_MD4Update(&ctx, (unsigned char *) input->data,
		   (unsigned int) input->length);
    krb5_MD4Final(&ctx);

    /* construct the buffer to be encrypted */

    memcpy(output->data, conf, CONFLENGTH);
    memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD4_CKSUM_LENGTH);

    /* encrypt it, in place.  this has a return value, but it's
       always zero.  */

    mit_des_cbc_encrypt((krb5_pointer) output->data,
			(krb5_pointer) output->data, output->length,
			schedule, (const unsigned char *) mit_des_zeroblock,
			1);

    return(0);
}
示例#20
0
/*ARGSUSED*/
static krb5_error_code
k5_md5des_hash(krb5_context context,
	krb5_const krb5_keyblock *key,
	krb5_keyusage usage,
	krb5_const krb5_data *ivec,
	krb5_const krb5_data *input, krb5_data *output)
{
    krb5_error_code ret = 0;
    krb5_data data;
    unsigned char conf[CONFLENGTH];
    unsigned char xorkey[MIT_DES_KEYSIZE];
    int i;
    krb5_data *hash_input;
    char *outptr;
    krb5_keyblock newkey;

    if (key->length != MIT_DES_KEYSIZE)
	return(KRB5_BAD_KEYSIZE);
    if (ivec)
	return(KRB5_CRYPTO_INTERNAL);
    if (output->length != (CONFLENGTH + MD5_CKSUM_LENGTH))
	return(KRB5_CRYPTO_INTERNAL);

    /* create the confounder */
    data.length = CONFLENGTH;
    data.data = (char *) conf;
    if ((ret = krb5_c_random_make_octets(context, &data)))
	return(ret);
    
    /* hash the confounder, then the input data */
    hash_input = (krb5_data *)MALLOC(sizeof(krb5_data) * 2);
    if (hash_input == NULL)
	return(KRB5_RC_MALLOC);

    hash_input[0].data = (char *)conf;
    hash_input[0].length = CONFLENGTH;
    hash_input[1].data = input->data;
    hash_input[1].length = input->length;

    /* Save the pointer to the beginning of the output buffer */
    outptr = (char *)output->data;

    /*
     * Move the output ptr ahead so we can write the hash
     * digest directly into the buffer.
     */
    output->data = output->data + CONFLENGTH;

    /* Use generic hash function that calls to kEF */
    if (k5_ef_hash(context, 2, hash_input, output)) {
	FREE(hash_input, sizeof(krb5_data) * 2);
	return(KRB5_KEF_ERROR);
    }

    /* restore the original ptr to the output data */
    output->data = outptr;

    /*
     * Put the confounder in the beginning of the buffer to be
     * encrypted.
     */
    bcopy(conf, output->data, CONFLENGTH); 

    bcopy(key->contents, xorkey, sizeof(xorkey));
    for (i=0; i<sizeof(xorkey); i++)
	xorkey[i] ^= 0xf0;

    /*
     * Solaris Kerberos:
     * Encryption Framework checks for parity and weak keys.
     */
    bzero(&newkey, sizeof(krb5_keyblock));
    newkey.enctype = key->enctype;
    newkey.contents = xorkey;
    newkey.length = sizeof(xorkey);
    newkey.dk_list = NULL;
    newkey.kef_key.ck_data = NULL;
    ret = init_key_kef(context->kef_cipher_mt, &newkey);
    if (ret) {
	FREE(hash_input, sizeof(krb5_data) * 2);
	return (ret);
    }

    /* encrypt it, in place.  this has a return value, but it's
       always zero.  */
    ret = mit_des_cbc_encrypt(context, (krb5_pointer) output->data,
	(krb5_pointer) output->data, output->length,
	&newkey, (unsigned char*) mit_des_zeroblock, 1);

    FREE(hash_input, sizeof(krb5_data) * 2);
    (void)crypto_destroy_ctx_template(newkey.key_tmpl);
    return(ret);
}