Blame src/lib/crypto/builtin/des/d3_aead.c

Packit Service 12ccfb
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit Service 12ccfb
/*
Packit Service 12ccfb
 * Copyright (C) 2008 by the Massachusetts Institute of Technology.
Packit Service 12ccfb
 * Copyright 1995 by Richard P. Basch.  All Rights Reserved.
Packit Service 12ccfb
 * Copyright 1995 by Lehman Brothers, Inc.  All Rights Reserved.
Packit Service 12ccfb
 *
Packit Service 12ccfb
 * Export of this software from the United States of America may
Packit Service 12ccfb
 *   require a specific license from the United States Government.
Packit Service 12ccfb
 *   It is the responsibility of any person or organization contemplating
Packit Service 12ccfb
 *   export to obtain such a license before exporting.
Packit Service 12ccfb
 *
Packit Service 12ccfb
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
Packit Service 12ccfb
 * distribute this software and its documentation for any purpose and
Packit Service 12ccfb
 * without fee is hereby granted, provided that the above copyright
Packit Service 12ccfb
 * notice appear in all copies and that both that copyright notice and
Packit Service 12ccfb
 * this permission notice appear in supporting documentation, and that
Packit Service 12ccfb
 * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
Packit Service 12ccfb
 * in advertising or publicity pertaining to distribution of the software
Packit Service 12ccfb
 * without specific, written prior permission.  Richard P. Basch,
Packit Service 12ccfb
 * Lehman Brothers and M.I.T. make no representations about the suitability
Packit Service 12ccfb
 * of this software for any purpose.  It is provided "as is" without
Packit Service 12ccfb
 * express or implied warranty.
Packit Service 12ccfb
 */
Packit Service 12ccfb
Packit Service 12ccfb
#include "crypto_int.h"
Packit Service 12ccfb
#include "des_int.h"
Packit Service 12ccfb
#include "f_tables.h"
Packit Service 12ccfb
Packit Service 12ccfb
void
Packit Service 12ccfb
krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
Packit Service 12ccfb
                         const mit_des_key_schedule ks1,
Packit Service 12ccfb
                         const mit_des_key_schedule ks2,
Packit Service 12ccfb
                         const mit_des_key_schedule ks3,
Packit Service 12ccfb
                         mit_des_cblock ivec)
Packit Service 12ccfb
{
Packit Service 12ccfb
    unsigned DES_INT32 left, right;
Packit Service 12ccfb
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
Packit Service 12ccfb
    const unsigned char *ip;
Packit Service 12ccfb
    struct iov_cursor cursor;
Packit Service 12ccfb
    unsigned char block[MIT_DES_BLOCK_LENGTH];
Packit Service 12ccfb
Packit Service 12ccfb
    /* Get key pointers here.  These won't need to be reinitialized. */
Packit Service 12ccfb
    kp1 = (const unsigned DES_INT32 *)ks1;
Packit Service 12ccfb
    kp2 = (const unsigned DES_INT32 *)ks2;
Packit Service 12ccfb
    kp3 = (const unsigned DES_INT32 *)ks3;
Packit Service 12ccfb
Packit Service 12ccfb
    /* Initialize left and right with the contents of the initial vector. */
Packit Service 12ccfb
    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
Packit Service 12ccfb
    left = load_32_be(ip);
Packit Service 12ccfb
    right = load_32_be(ip + 4);
Packit Service 12ccfb
Packit Service 12ccfb
    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
Packit Service 12ccfb
    while (k5_iov_cursor_get(&cursor, block)) {
Packit Service 12ccfb
        /* xor this block with the previous ciphertext. */
Packit Service 12ccfb
        left ^= load_32_be(block);
Packit Service 12ccfb
        right ^= load_32_be(block + 4);
Packit Service 12ccfb
Packit Service 12ccfb
        /* Encrypt what we have and store it back into block. */
Packit Service 12ccfb
        DES_DO_ENCRYPT(left, right, kp1);
Packit Service 12ccfb
        DES_DO_DECRYPT(left, right, kp2);
Packit Service 12ccfb
        DES_DO_ENCRYPT(left, right, kp3);
Packit Service 12ccfb
        store_32_be(left, block);
Packit Service 12ccfb
        store_32_be(right, block + 4);
Packit Service 12ccfb
Packit Service 12ccfb
        k5_iov_cursor_put(&cursor, block);
Packit Service 12ccfb
    }
Packit Service 12ccfb
Packit Service 12ccfb
    if (ivec != NULL) {
Packit Service 12ccfb
        store_32_be(left, ivec);
Packit Service 12ccfb
        store_32_be(right, ivec + 4);
Packit Service 12ccfb
    }
Packit Service 12ccfb
}
Packit Service 12ccfb
Packit Service 12ccfb
void
Packit Service 12ccfb
krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
Packit Service 12ccfb
                         const mit_des_key_schedule ks1,
Packit Service 12ccfb
                         const mit_des_key_schedule ks2,
Packit Service 12ccfb
                         const mit_des_key_schedule ks3,
Packit Service 12ccfb
                         mit_des_cblock ivec)
Packit Service 12ccfb
{
Packit Service 12ccfb
    unsigned DES_INT32 left, right;
Packit Service 12ccfb
    const unsigned DES_INT32 *kp1, *kp2, *kp3;
Packit Service 12ccfb
    const unsigned char *ip;
Packit Service 12ccfb
    unsigned DES_INT32 ocipherl, ocipherr;
Packit Service 12ccfb
    unsigned DES_INT32 cipherl, cipherr;
Packit Service 12ccfb
    struct iov_cursor cursor;
Packit Service 12ccfb
    unsigned char block[MIT_DES_BLOCK_LENGTH];
Packit Service 12ccfb
Packit Service 12ccfb
    /* Get key pointers here.  These won't need to be reinitialized. */
Packit Service 12ccfb
    kp1 = (const unsigned DES_INT32 *)ks1;
Packit Service 12ccfb
    kp2 = (const unsigned DES_INT32 *)ks2;
Packit Service 12ccfb
    kp3 = (const unsigned DES_INT32 *)ks3;
Packit Service 12ccfb
Packit Service 12ccfb
    /*
Packit Service 12ccfb
     * Decrypting is harder than encrypting because of
Packit Service 12ccfb
     * the necessity of remembering a lot more things.
Packit Service 12ccfb
     * Should think about this a little more...
Packit Service 12ccfb
     */
Packit Service 12ccfb
Packit Service 12ccfb
    /* Prime the old cipher with ivec.*/
Packit Service 12ccfb
    ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
Packit Service 12ccfb
    ocipherl = load_32_be(ip);
Packit Service 12ccfb
    ocipherr = load_32_be(ip + 4);
Packit Service 12ccfb
Packit Service 12ccfb
    k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
Packit Service 12ccfb
    while (k5_iov_cursor_get(&cursor, block)) {
Packit Service 12ccfb
        /* Split this block into left and right. */
Packit Service 12ccfb
        cipherl = left = load_32_be(block);
Packit Service 12ccfb
        cipherr = right = load_32_be(block + 4);
Packit Service 12ccfb
Packit Service 12ccfb
        /* Decrypt and xor with the old cipher to get plain text. */
Packit Service 12ccfb
        DES_DO_DECRYPT(left, right, kp3);
Packit Service 12ccfb
        DES_DO_ENCRYPT(left, right, kp2);
Packit Service 12ccfb
        DES_DO_DECRYPT(left, right, kp1);
Packit Service 12ccfb
        left ^= ocipherl;
Packit Service 12ccfb
        right ^= ocipherr;
Packit Service 12ccfb
Packit Service 12ccfb
        /* Store the encrypted halves back into block. */
Packit Service 12ccfb
        store_32_be(left, block);
Packit Service 12ccfb
        store_32_be(right, block + 4);
Packit Service 12ccfb
Packit Service 12ccfb
        /* Save current cipher block halves. */
Packit Service 12ccfb
        ocipherl = cipherl;
Packit Service 12ccfb
        ocipherr = cipherr;
Packit Service 12ccfb
Packit Service 12ccfb
        k5_iov_cursor_put(&cursor, block);
Packit Service 12ccfb
    }
Packit Service 12ccfb
Packit Service 12ccfb
    if (ivec != NULL) {
Packit Service 12ccfb
        store_32_be(ocipherl, ivec);
Packit Service 12ccfb
        store_32_be(ocipherr, ivec + 4);
Packit Service 12ccfb
    }
Packit Service 12ccfb
}