Component idea

You are here: All Systems / ironclad / idea

;;;; idea.lisp -- implementation of the IDEA block cipher

;;; converted mostly from the C code appearing in _Applied Cryptography_
;;; by Bruce Schneier to Common Lisp.  Beware the C-isms.

(in-package :crypto)

(defun idea-mul (a b)
  (declare (type (unsigned-byte 16) a b))
  (cond
    ((zerop a) (ldb (byte 16 0) (- 1 b)))
    ((zerop b) (ldb (byte 16 0) (- 1 a)))
    (t
     (let* ((product (ldb (byte 32 0) (* a b)))
            (x (ldb (byte 16 16) product))
            (y (ldb (byte 16 0) product))
)

       (ldb (byte 16 0) (+ (- y x) (if (< y x) 1 0)))
)
)
)
)


(defun idea-mul-inv (x)
  (declare (type (unsigned-byte 16) x))
  (let ((t1 1))
    (declare (type (unsigned-byte 16) t1))
    (when (<= x 1)
      (return-from idea-mul-inv x)
)

    (multiple-value-bind (t0 y) (truncate 65537 x)
      (declare (type (unsigned-byte 16) t0 y))
      (loop until (= y 1)
        do (let ((q (truncate x y)))
             (declare (type (unsigned-byte 16) q))
             (setf x (mod x y))
             (incf t1 (ldb (byte 16 0) (* q t0)))
             (when (= x 1)
               (return-from idea-mul-inv t1)
)

             (setf q (truncate y x))
             (setf y (mod y x))
             (incf t0 (ldb (byte 16 0) (* q t1)))
)

        finally (return (ldb (byte 16 0) (- 1 t0)))
)
)
)
)


(deftype idea-round-keys () '(simple-array (unsigned-byte 16) (52)))

(defun idea-munge-block (input input-start output output-start keys)
  (declare (type (simple-array (unsigned-byte 8) (*)) input output))
  (declare (type (integer 0 #.(- array-dimension-limit 8))
                 input-start output-start
)
)

  (declare (type idea-round-keys keys))
  (with-words ((x1 x2 x3 x4) input input-start :size 2)
    (do ((i 0 (+ i 6)))
        ((>= i 48)
         ;; final round
        (setf x1 (idea-mul x1 (aref keys 48))
               x2 (ldb (byte 16 0) (+ x2 (aref keys 50)))
               x3 (ldb (byte 16 0) (+ x3 (aref keys 49)))
               x4 (idea-mul x4 (aref keys 51))
)

         (store-words output output-start x1 x3 x2 x4)
)

      (setf x1 (idea-mul x1 (aref keys i))
            x2 (ldb (byte 16 0) (+ x2 (aref keys (+ i 1))))
            x3 (ldb (byte 16 0) (+ x3 (aref keys (+ i 2))))
            x4 (idea-mul x4 (aref keys (+ i 3)))
)

      (let ((t1 x3)
            (t0 x2)
)

        (setf x3 (idea-mul (logxor x3 x1) (aref keys (+ i 4)))
              x2 (idea-mul (ldb (byte 16 0)
                                (+ (logxor x2 x4) x3)
)

                           (aref keys (+ i 5))
)
)

        (setf x3 (ldb (byte 16 0) (+ x3 x2))
              x1 (logxor x1 x2)
              x4 (logxor x4 x3)
              x2 (logxor x2 t1)
              x3 (logxor x3 t0)
)
)
)
)
)


(defclass idea-context (cipher 8-byte-block-mixin)
  ((encryption-keys :accessor encryption-keys)
   (decryption-keys :accessor decryption-keys)
)
)


(define-block-encryptor idea 8
  (idea-munge-block plaintext plaintext-start ciphertext ciphertext-start
                    (encryption-keys context)
)
)


(define-block-decryptor idea 8
  (idea-munge-block ciphertext ciphertext-start plaintext plaintext-start
                    (decryption-keys context)
)
)


(defun idea-invert-key (encryption-keys decryption-keys)
  (declare (type idea-round-keys encryption-keys decryption-keys))
  (setf (aref decryption-keys 51) (idea-mul-inv (aref encryption-keys 3))
        (aref decryption-keys 50) (ldb (byte 16 0) (- (aref encryption-keys 2)))
        (aref decryption-keys 49) (ldb (byte 16 0) (- (aref encryption-keys 1)))
        (aref decryption-keys 48) (idea-mul-inv (aref encryption-keys 0))
)

  (do ((i 1 (1+ i))
       (k 4 (+ k 6))
       (counter 47)
)

      ((>= i 8)
       (setf (aref decryption-keys 5) (aref encryption-keys 47)
             (aref decryption-keys 4) (aref encryption-keys 46)
             (aref decryption-keys 3) (idea-mul-inv (aref encryption-keys 51))
             (aref decryption-keys 2) (ldb (byte 16 0) (- (aref encryption-keys 50)))
             (aref decryption-keys 1) (ldb (byte 16 0) (- (aref encryption-keys 49)))
             (aref decryption-keys 0) (idea-mul-inv (aref encryption-keys 48))
)

       decryption-keys
)

    (flet ((set-decryption-key (x)
             (setf (aref decryption-keys counter) x)
             (decf counter)
)
)

      (declare (inline set-decryption-key))
    (set-decryption-key (aref encryption-keys (+ k 1)))
    (set-decryption-key (aref encryption-keys k))
    (set-decryption-key (idea-mul-inv (aref encryption-keys (+ k 5))))
    (set-decryption-key (ldb (byte 16 0) (- (aref encryption-keys (+ k 3)))))
    (set-decryption-key (ldb (byte 16 0) (- (aref encryption-keys (+ k 4)))))
    (set-decryption-key (idea-mul-inv (aref encryption-keys (+ k 2))))
)
)
)


(defun idea-key-schedule (key)
  (declare (type (simple-array (unsigned-byte 8) (16)) key))
  (let ((encryption-keys (make-array 52 :element-type '(unsigned-byte 16)))
        (decryption-keys (make-array 52 :element-type '(unsigned-byte 16)))
)

    (declare (type idea-round-keys encryption-keys decryption-keys))
    (dotimes (i 8)
      (setf (aref encryption-keys i) (ub16ref/be key (* i 2)))
)

    (do ((j 1 (1+ (mod j 8)))
         (k 8 (1+ k))
         (offset 0)
)

        ((>= k 52) (values encryption-keys (idea-invert-key encryption-keys
                                                           decryption-keys
)
)
)

      (setf (aref encryption-keys (+ j 7 offset))
            (ldb (byte 16 0)
                 (logior (ash (aref encryption-keys (+ (mod j 8) offset)) 9)
                         (ash (aref encryption-keys (+ (mod (1+ j) 8) offset)) -7)
)
)
)

      (incf offset (if (= j 8) 8 0))
)
)
)


(defmethod schedule-key ((cipher idea-context) key)
  (declare (type (simple-array (unsigned-byte 8) (16)) key))
  (multiple-value-bind (encryption-keys decryption-keys)
      (idea-key-schedule key)
    (setf (encryption-keys cipher) encryption-keys
          (decryption-keys cipher) decryption-keys
)

    cipher
)
)


(defcipher idea
  (:encrypt-function idea-encrypt-block)
  (:decrypt-function idea-decrypt-block)
  (:block-length 8)
  (:key-length (:fixed 16))
)

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.