Beispiel #1
0
void
krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
                        const mit_des_key_schedule schedule,
                        mit_des_cblock ivec)
{
    unsigned DES_INT32 left, right;
    const unsigned DES_INT32 *kp;
    const unsigned char *ip;
    struct iov_block_state input_pos, output_pos;
    unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;

    IOV_BLOCK_STATE_INIT(&input_pos);
    IOV_BLOCK_STATE_INIT(&output_pos);

    /* Get key pointer here.  This won't need to be reinitialized. */
    kp = (const unsigned DES_INT32 *)schedule;

    /* Initialize left and right with the contents of the initial vector. */
    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
    GET_HALF_BLOCK(left, ip);
    GET_HALF_BLOCK(right, ip);

    /* Work the length down 8 bytes at a time. */
    for (;;) {
        unsigned DES_INT32 temp;

        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
                                            data, num_data, &input_pos, &ptr))
            break;
        block = ptr;

        /* Decompose this block and xor it with the previous ciphertext. */
        GET_HALF_BLOCK(temp, ptr);
        left  ^= temp;
        GET_HALF_BLOCK(temp, ptr);
        right ^= temp;

        /* Encrypt what we have and put back into block. */
        DES_DO_ENCRYPT(left, right, kp);
        ptr = block;
        PUT_HALF_BLOCK(left, ptr);
        PUT_HALF_BLOCK(right, ptr);

        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
                                       MIT_DES_BLOCK_LENGTH, &output_pos,
                                       block);
    }

    if (ivec != NULL && block != NULL) {
        ptr = ivec;
        PUT_HALF_BLOCK(left, ptr);
        PUT_HALF_BLOCK(right, ptr);
    }
}
Beispiel #2
0
unsigned long
mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out,
                  unsigned long length, const mit_des_key_schedule schedule,
                  const krb5_octet *ivec)
{
    unsigned DES_INT32 left, right;
    const unsigned DES_INT32 *kp;
    const unsigned char *ip;
    unsigned char *op;
    register DES_INT32 len;

    /*
     * Initialize left and right with the contents of the initial
     * vector.
     */
    ip = ivec;
    GET_HALF_BLOCK(left, ip);
    GET_HALF_BLOCK(right, ip);

    /*
     * Suitably initialized, now work the length down 8 bytes
     * at a time.
     */
    ip = in;
    len = length;
    while (len > 0) {
        /*
         * Get more input, xor it in.  If the length is
         * greater than or equal to 8 this is straight
         * forward.  Otherwise we have to fart around.
         */
        if (len >= 8) {
            unsigned DES_INT32 temp;
            GET_HALF_BLOCK(temp, ip);
            left  ^= temp;
            GET_HALF_BLOCK(temp, ip);
            right ^= temp;
            len -= 8;
        } else {
            /*
             * Oh, shoot.  We need to pad the
             * end with zeroes.  Work backwards
             * to do this.
             */
            ip += (int) len;
            switch(len) {
            case 7:
                right ^= (*(--ip) & FF_UINT32) <<  8;
            case 6:
                right ^= (*(--ip) & FF_UINT32) << 16;
            case 5:
                right ^= (*(--ip) & FF_UINT32) << 24;
            case 4:
                left  ^=  *(--ip) & FF_UINT32;
            case 3:
                left  ^= (*(--ip) & FF_UINT32) <<  8;
            case 2:
                left  ^= (*(--ip) & FF_UINT32) << 16;
            case 1:
                left  ^= (*(--ip) & FF_UINT32) << 24;
                break;
            }
            len = 0;
        }

        /*
         * Encrypt what we have
         */
        kp = (const unsigned DES_INT32 *)schedule;
        DES_DO_ENCRYPT(left, right, kp);
    }

    /*
     * Done.  Left and right have the checksum.  Put it into
     * the output.
     */
    op = out;
    PUT_HALF_BLOCK(left, op);
    PUT_HALF_BLOCK(right, op);

    /*
     * Return right.  I'll bet the MIT code returns this
     * inconsistantly (with the low order byte of the checksum
     * not always in the low order byte of the DES_INT32).  We won't.
     */
    return right & 0xFFFFFFFFUL;
}
Beispiel #3
0
void
krb5int_des_cbc_encrypt(const mit_des_cblock *in,
			mit_des_cblock *out,
			unsigned long length,
			const mit_des_key_schedule schedule,
			const mit_des_cblock ivec)
{
	unsigned DES_INT32 left, right;
	const unsigned DES_INT32 *kp;
	const unsigned char *ip;
	unsigned char *op;

	/*
	 * Get key pointer here.  This won't need to be reinitialized
	 */
	kp = (const unsigned DES_INT32 *)schedule;

	/*
	 * Initialize left and right with the contents of the initial
	 * vector.
	 */
	ip = ivec;
	GET_HALF_BLOCK(left, ip);
	GET_HALF_BLOCK(right, ip);

	/*
	 * Suitably initialized, now work the length down 8 bytes
	 * at a time.
	 */
	ip = *in;
	op = *out;
	while (length > 0) {
		/*
		 * Get more input, xor it in.  If the length is
		 * greater than or equal to 8 this is straight
		 * forward.  Otherwise we have to fart around.
		 */
		if (length >= 8) {
			unsigned DES_INT32 temp;
			GET_HALF_BLOCK(temp, ip);
			left  ^= temp;
			GET_HALF_BLOCK(temp, ip);
			right ^= temp;
			length -= 8;
		} else {
			/*
			 * Oh, shoot.  We need to pad the
			 * end with zeroes.  Work backwards
			 * to do this.
			 */
			ip += (int) length;
			switch(length) {
			case 7:
				right ^= (*(--ip) & FF_UINT32) <<  8;
			case 6:
				right ^= (*(--ip) & FF_UINT32) << 16;
			case 5:
				right ^= (*(--ip) & FF_UINT32) << 24;
			case 4:
				left  ^=  *(--ip) & FF_UINT32;
			case 3:
				left  ^= (*(--ip) & FF_UINT32) <<  8;
			case 2:
				left  ^= (*(--ip) & FF_UINT32) << 16;
			case 1:
				left  ^= (*(--ip) & FF_UINT32) << 24;
				break;
			}
			length = 0;
		}

		/*
		 * Encrypt what we have
		 */
		DES_DO_ENCRYPT(left, right, kp);

		/*
		 * Copy the results out
		 */
		PUT_HALF_BLOCK(left, op);
		PUT_HALF_BLOCK(right, op);
	}
}
Beispiel #4
0
void
krb5int_des_cbc_decrypt(const mit_des_cblock *in,
			mit_des_cblock *out,
			unsigned long length,
			const mit_des_key_schedule schedule,
			const mit_des_cblock ivec)
{
	unsigned DES_INT32 left, right;
	const unsigned DES_INT32 *kp;
	const unsigned char *ip;
	unsigned char *op;
	unsigned DES_INT32 ocipherl, ocipherr;
	unsigned DES_INT32 cipherl, cipherr;

	/*
	 * Get key pointer here.  This won't need to be reinitialized
	 */
	kp = (const unsigned DES_INT32 *)schedule;

	/*
	 * Decrypting is harder than encrypting because of
	 * the necessity of remembering a lot more things.
	 * Should think about this a little more...
	 */

	if (length <= 0)
		return;

	/*
	 * Prime the old cipher with ivec.
	 */
	ip = ivec;
	GET_HALF_BLOCK(ocipherl, ip);
	GET_HALF_BLOCK(ocipherr, ip);

	/*
	 * Now do this in earnest until we run out of length.
	 */
	ip = *in;
	op = *out;
	for (;;) {		/* check done inside loop */
		/*
		 * Read a block from the input into left and
		 * right.  Save this cipher block for later.
		 */
		GET_HALF_BLOCK(left, ip);
		GET_HALF_BLOCK(right, ip);
		cipherl = left;
		cipherr = right;

		/*
		 * Decrypt this.
		 */
		DES_DO_DECRYPT(left, right, kp);

		/*
		 * Xor with the old cipher to get plain
		 * text.  Output 8 or less bytes of this.
		 */
		left ^= ocipherl;
		right ^= ocipherr;
		if (length > 8) {
			length -= 8;
			PUT_HALF_BLOCK(left, op);
			PUT_HALF_BLOCK(right, op);
			/*
			 * Save current cipher block here
			 */
			ocipherl = cipherl;
			ocipherr = cipherr;
		} else {
			/*
			 * Trouble here.  Start at end of output,
			 * work backwards.
			 */
			op += (int) length;
			switch(length) {
			case 8:
				*(--op) = (unsigned char) (right & 0xff);
			case 7:
				*(--op) = (unsigned char) ((right >> 8) & 0xff);
			case 6:
				*(--op) = (unsigned char) ((right >> 16) & 0xff);
			case 5:
				*(--op) = (unsigned char) ((right >> 24) & 0xff);
			case 4:
				*(--op) = (unsigned char) (left & 0xff);
			case 3:
				*(--op) = (unsigned char) ((left >> 8) & 0xff);
			case 2:
				*(--op) = (unsigned char) ((left >> 16) & 0xff);
			case 1:
				*(--op) = (unsigned char) ((left >> 24) & 0xff);
				break;
			}
			break;		/* we're done */
		}
	}
}
Beispiel #5
0
void
krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data,
			     unsigned long num_data,
			     const mit_des_key_schedule ks1,
			     const mit_des_key_schedule ks2,
			     const mit_des_key_schedule ks3,
			     mit_des_cblock ivec)
{
    unsigned DES_INT32 left, right;
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
    const unsigned char *ip;
    unsigned char *op;
    struct iov_block_state input_pos, output_pos;
    unsigned char iblock[MIT_DES_BLOCK_LENGTH];
    unsigned char oblock[MIT_DES_BLOCK_LENGTH];

    IOV_BLOCK_STATE_INIT(&input_pos);
    IOV_BLOCK_STATE_INIT(&output_pos);

    /*
     * Get key pointer here.  This won't need to be reinitialized
     */
    kp1 = (const unsigned DES_INT32 *)ks1;
    kp2 = (const unsigned DES_INT32 *)ks2;
    kp3 = (const unsigned DES_INT32 *)ks3;

    /*
     * Initialize left and right with the contents of the initial
     * vector.
     */
    if (ivec != NULL)
	ip = ivec;
    else
	ip = mit_des_zeroblock;
    GET_HALF_BLOCK(left, ip);
    GET_HALF_BLOCK(right, ip);

    /*
     * Suitably initialized, now work the length down 8 bytes
     * at a time.
     */
    for (;;) {
	unsigned DES_INT32 temp;

	ip = iblock;
	op = oblock;

	if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
	    break;

	if (input_pos.iov_pos == num_data)
	    break;

	GET_HALF_BLOCK(temp, ip);
	left  ^= temp;
	GET_HALF_BLOCK(temp, ip);
	right ^= temp;

	/*
	 * Encrypt what we have
	 */
	DES_DO_ENCRYPT(left, right, kp1);
	DES_DO_DECRYPT(left, right, kp2);
	DES_DO_ENCRYPT(left, right, kp3);

	/*
	 * Copy the results out
	 */
	PUT_HALF_BLOCK(left, op);
	PUT_HALF_BLOCK(right, op);

	krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
    }

    if (ivec != NULL)
	memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH);
}
Beispiel #6
0
void
krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
			     unsigned long num_data,
			     const mit_des_key_schedule ks1,
			     const mit_des_key_schedule ks2,
			     const mit_des_key_schedule ks3,
			     mit_des_cblock ivec)
{
    unsigned DES_INT32 left, right;
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
    const unsigned char *ip;
    unsigned DES_INT32 ocipherl, ocipherr;
    unsigned DES_INT32 cipherl, cipherr;
    unsigned char *op;
    struct iov_block_state input_pos, output_pos;
    unsigned char iblock[MIT_DES_BLOCK_LENGTH];
    unsigned char oblock[MIT_DES_BLOCK_LENGTH];

    IOV_BLOCK_STATE_INIT(&input_pos);
    IOV_BLOCK_STATE_INIT(&output_pos);

    /*
     * Get key pointer here.  This won't need to be reinitialized
     */
    kp1 = (const unsigned DES_INT32 *)ks1;
    kp2 = (const unsigned DES_INT32 *)ks2;
    kp3 = (const unsigned DES_INT32 *)ks3;

    /*
     * Decrypting is harder than encrypting because of
     * the necessity of remembering a lot more things.
     * Should think about this a little more...
     */

    if (num_data == 0)
	return;

    /*
     * Prime the old cipher with ivec.
     */
    if (ivec != NULL)
	ip = ivec;
    else
	ip = mit_des_zeroblock;
    GET_HALF_BLOCK(ocipherl, ip);
    GET_HALF_BLOCK(ocipherr, ip);

    /*
     * Now do this in earnest until we run out of length.
     */
    for (;;) {
	/*
	 * Read a block from the input into left and
	 * right.  Save this cipher block for later.
	 */

	if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
	    break;

	if (input_pos.iov_pos == num_data)
	    break;

	ip = iblock;
	op = oblock;

	GET_HALF_BLOCK(left, ip);
	GET_HALF_BLOCK(right, ip);
	cipherl = left;
	cipherr = right;

	/*
	 * Decrypt this.
	 */
	DES_DO_DECRYPT(left, right, kp3);
	DES_DO_ENCRYPT(left, right, kp2);
	DES_DO_DECRYPT(left, right, kp1);

	/*
	 * Xor with the old cipher to get plain
	 * text.  Output 8 or less bytes of this.
	 */
	left ^= ocipherl;
	right ^= ocipherr;

	PUT_HALF_BLOCK(left, op);
	PUT_HALF_BLOCK(right, op);

	/*
	 * Save current cipher block here
	 */
	ocipherl = cipherl;
	ocipherr = cipherr;

	krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
    }

    if (ivec != NULL) {
	op = ivec;
	PUT_HALF_BLOCK(ocipherl,op);
	PUT_HALF_BLOCK(ocipherr, op);
    }
}
Beispiel #7
0
void
krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
                        const mit_des_key_schedule schedule,
                        mit_des_cblock ivec)
{
    unsigned DES_INT32 left, right;
    const unsigned DES_INT32 *kp;
    const unsigned char *ip;
    unsigned DES_INT32 ocipherl, ocipherr;
    unsigned DES_INT32 cipherl, cipherr;
    struct iov_block_state input_pos, output_pos;
    unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;

    IOV_BLOCK_STATE_INIT(&input_pos);
    IOV_BLOCK_STATE_INIT(&output_pos);

    /* Get key pointer here.  This won't need to be reinitialized. */
    kp = (const unsigned DES_INT32 *)schedule;

    /*
     * Decrypting is harder than encrypting because of
     * the necessity of remembering a lot more things.
     * Should think about this a little more...
     */

    /* Prime the old cipher with ivec. */
    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
    GET_HALF_BLOCK(ocipherl, ip);
    GET_HALF_BLOCK(ocipherr, ip);

    /* Work the length down 8 bytes at a time. */
    for (;;) {
        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
                                            data, num_data, &input_pos, &ptr))
            break;
        block = ptr;

        /* Split this block into left and right. */
        GET_HALF_BLOCK(left, ptr);
        GET_HALF_BLOCK(right, ptr);
        cipherl = left;
        cipherr = right;

        /* Decrypt and xor with the old cipher to get plain text. */
        DES_DO_DECRYPT(left, right, kp);
        left ^= ocipherl;
        right ^= ocipherr;

        /* Store the encrypted halves back into block. */
        ptr = block;
        PUT_HALF_BLOCK(left, ptr);
        PUT_HALF_BLOCK(right, ptr);

        /* Save current cipher block halves. */
        ocipherl = cipherl;
        ocipherr = cipherr;

        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
                                       MIT_DES_BLOCK_LENGTH, &output_pos,
                                       block);
    }

    if (ivec != NULL && block != NULL) {
        ptr = ivec;
        PUT_HALF_BLOCK(ocipherl, ptr);
        PUT_HALF_BLOCK(ocipherr, ptr);
    }
}