packages feed

cpsa-3.6.0: doc/examples/pkinit.scm

(herald "Kerberos PKINIT")

;;; This file includes three versions of the Kerberos PKINIT
;;; protocol. The first version is the flawed version that Cervesato
;;; et al. analyzed in "Breaking and Fixing Public-Key Kerberos." The
;;; other two versions are the two fixes that are explored in the same
;;; paper.

;;; We also express the goal that the authors identify as a property
;;; not met by the original flawed version, but which both fixes do
;;; achieve. Running CPSA with this input demonstrates that the flawed
;;; version does not satisfy the goal, but both fixed versions do.

;;; How to use this file:
;;;
;;; CPSA looks at the goal and creates an initial point of view that
;;; corresponds to the information contained in the antecedent of the
;;; implication of the goal. It then outputs a characterization
;;; (consisting of shapes) of all executions containing at least the
;;; structure contained in the point of view. It then evaluates the
;;; goal against each of those shapes. The guarantee CPSA provides is
;;; that a goal is achieved iff each of the shapes satisfies the goal.

;;; We can look at the output in pkinit.xhtml to determine what CPSA
;;; discovered. Notice that the shape associated with the first
;;; analysis (of the flawed version) contains an annotation that says
;;; (satisfies (no (c c) (as as) (k k) (z (0 1)))). This means that
;;; the goal is not satisfied. The pairs of terms represent a variable
;;; assignment for the logical variables of the goal into elements of
;;; the shape. This is the variable assignment of the antecendant
;;; which has no extension for which the conclusion is also
;;; satisfied. The shapes for the other analyses contain the
;;; annotation (satisfies yes) indicating that the goal is satisfied
;;; in the shape (and hence in any realized skeleton).

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                       ;;
;; Protocol Descriptions ;;
;;                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; This is the flawed version of the Kerberos public key initial
;; round.
(defprotocol pkinit-flawed basic
  (defrole client
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (send (cat (enc tc n2 (privk c)) c t n1))
      (recv
        (cat (enc (enc k n2 (privk as)) (pubk c)) c tgt
          (enc ak n1 tk t k))))
    (uniq-orig n1 n2))
  (defrole auth
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (recv (cat (enc tc n2 (privk c)) c t n1))
      (send
        (cat (enc (enc k n2 (privk as)) (pubk c)) c tgt
          (enc ak n1 tk t k))))
    (uniq-orig k ak)))

;; This is the fix the authors proposed to the standards group. It
;; adds the value c in a new field inside the server's signature.
(defprotocol pkinit-fix1 basic
  (defrole client
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (send (cat (enc tc n2 (privk c)) c t n1))
      (recv
        (cat (enc (enc k n2 c (privk as)) (pubk c)) c tgt
          (enc ak n1 tk t k))))
    (uniq-orig n1 n2))
  (defrole auth
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (recv (cat (enc tc n2 (privk c)) c t n1))
      (send
        (cat (enc (enc k n2 c (privk as)) (pubk c)) c tgt
          (enc ak n1 tk t k))))
    (uniq-orig k ak)))

;; This is the fix that the standards group proposed and adopted. It
;; replaces n2 in the server's with a hash of the entire first
;; message.
(defprotocol pkinit-fix2 basic
  (defrole client
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (send (cat (enc tc n2 (privk c)) c t n1))
      (recv
        (cat (enc (enc k (hash (cat (enc tc n2 (privk c)) c t n1))
                       (privk as)) (pubk c)) c tgt (enc ak n1 tk t k))))
    (uniq-orig n1 n2))
  (defrole auth
    (vars (c t as name) (n2 n1 text) (tc tk tgt data) (k ak skey))
    (trace (recv (cat (enc tc n2 (privk c)) c t n1))
      (send
        (cat (enc (enc k (hash (cat (enc tc n2 (privk c)) c t n1))
                       (privk as)) (pubk c)) c tgt (enc ak n1 tk t k))))
    (uniq-orig k ak)))

;;;;;;;;;;;;;;;;;;;;;
;;                 ;;
;; Goal Statements ;;
;;                 ;;
;;;;;;;;;;;;;;;;;;;;;

;; This is the goal that the authors discovered was not met by the
;; original, flawed version, but which was met by both fixes.
(defgoal pkinit-flawed
  (forall ((c as name) (k skey) (z strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (non (privk as))
                (non (privk c)))
           (exists ((z-0 strd))
                   (and (p "auth" z-0 2)
                        (p "auth" "as" z-0 as)
                        (p "auth" "k" z-0 k)
                        (p "auth" "c" z-0 c))))))

;; Since we reference the protocol in the expression of the goal, we
;; must repeat it once for every protocol against which we would like
;; to evaluate the goal.
(defgoal pkinit-fix1
  (forall ((c as name) (k skey) (z strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (non (privk as))
                (non (privk c)))
           (exists ((z-0 strd))
                   (and (p "auth" z-0 2)
                        (p "auth" "as" z-0 as)
                        (p "auth" "k" z-0 k)
                        (p "auth" "c" z-0 c))))))

;; Repeated once more.
(defgoal pkinit-fix2
  (forall ((c as name) (k skey) (z strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (non (privk as))
                (non (privk c)))
           (exists ((z-0 strd))
                   (and (p "auth" z-0 2)
                        (p "auth" "as" z-0 as)
                        (p "auth" "k" z-0 k)
                        (p "auth" "c" z-0 c))))))

;;;;;;;;

(defgoal pkinit-flawed
  (forall ((c c-0 as name) (k skey) (z z-0 strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (p "auth" z-0 2)
                (p "auth" "k" z-0 k)
                (p "auth" "c" z-0 c-0)
                (non (privk as))
                (non (privk c)))
           ;(exists ((z-1 strd))
           ;        (p "client" 1 z-1))
           (= c c-0)
           )))

(defgoal pkinit-fix1
  (forall ((c c-0 as name) (k skey) (z z-0 strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (p "auth" z-0 2)
                (p "auth" "k" z-0 k)
                (p "auth" "c" z-0 c-0)
                (non (privk as))
                (non (privk c)))
           (exists ((z-1 strd))
                   (p "client" z-1 2))
           ;(= c c-0)
           )))

(defgoal pkinit-fix2
  (forall ((c c-0 as name) (k skey) (z z-0 strd))
          (implies
           (and (p "client" z 2)
                (p "client" "c" z c)
                (p "client" "as" z as)
                (p "client" "k" z k)
                (p "auth" z-0 2)
                (p "auth" "k" z-0 k)
                (p "auth" "c" z-0 c-0)
                (non (privk as))
                (non (privk c)))
           (exists ((z-1 strd))
                   (p "client" z-1 2)))))