From: okada Date: Wed, 1 Dec 1999 15:39:27 +0000 (+0000) Subject: add scram-md5.el X-Git-Tag: slim-1_13_4~7 X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=6f0376a8c268756e120b9849cde406213404ff73;p=elisp%2Fflim.git add scram-md5.el --- diff --git a/ChangeLog b/ChangeLog index cbc97b1..19fe777 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +1999-12-02 Kenichi OKADA + + * scram-md5.el: New file. + * FLIM-ELS (flim-modules): Add `scram-md5'. + 1999-12-01 Kenichi OKADA * smtp.el (smtp-auth-anonymous): New function. diff --git a/FLIM-ELS b/FLIM-ELS index ae1b06f..7548a9a 100644 --- a/FLIM-ELS +++ b/FLIM-ELS @@ -14,6 +14,7 @@ md5 md5-el md5-dl sha1 sha1-el sha1-dl hmac-def hmac-md5 hmac-sha1 hex-util + scram-md5 starttls)) (unless (and (fboundp 'base64-encode-string) diff --git a/scram-md5.el b/scram-md5.el new file mode 100644 index 0000000..85efb08 --- /dev/null +++ b/scram-md5.el @@ -0,0 +1,127 @@ +;;; scram-md5.el --- Compute SCRAM-MD5. + +;; Copyright (C) 1999 Shuhei KOBAYASHI + +;; Author: Shuhei KOBAYASHI +;; Keywords: SCRAM-MD5, HMAC-MD5, SASL, IMAP, POP, ACAP + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This program is implemented from draft-newman-auth-scram-03.txt. +;; +;; It is caller's responsibility to base64-decode challenges and +;; base64-encode responses in IMAP4 AUTHENTICATE command. +;; +;; Passphrase should be longer than 16 bytes. (See RFC 2195) +;; +;; TODO: Provide higher-level (SASL) APIs. + +;;; Code: + +(require 'hmac-md5) ; (hmac-md5 TEXT KEY) + +(defmacro scram-security-info-no-security-layer (security-info) + `(eq (logand (aref ,security-info 0) 1) 1)) +(defmacro scram-security-info-integrity-protection-layer (security-info) + `(eq (logand (aref ,security-info 0) 2) 2)) +(defmacro scram-security-info-buffer-size (security-info) + `(let ((ssecinfo ,security-info)) + (+ (lsh (aref ssecinfo 1) 16) + (lsh (aref ssecinfo 2) 8) + (aref ssecinfo 3)))) + +(defun scram-make-security-info (integrity-protection-layer + no-security-layer buffer-size) + (let ((csecinfo (make-string 4 0))) + (when integrity-protection-layer + (aset csecinfo 0 2)) + (if no-security-layer + (aset csecinfo 0 (logior (aref csecinfo 0) 1)) + (aset csecinfo 1 + (lsh (logand buffer-size (lsh 255 16)) -16)) + (aset csecinfo 2 + (lsh (logand buffer-size (lsh 255 8)) -8)) + (aset csecinfo 3 (logand buffer-size 255))) + csecinfo)) + +(defun scram-make-unique-nonce () ; 8*OCTET, globally unique. + ;; For example, concatenated string of process-identifier, system-clock, + ;; sequence-number, random-number, and domain-name. + (concat "foo" "bar" "baz" "@" (system-name))) ; TEMPORARY + +(defun scram-xor-string (str1 str2) + ;; (length str1) == (length str2) == (length dst) == 16 (in SCRAM-MD5) + (let* ((len (length str1)) + (dst (make-string len 0)) + (pos 0)) + (while (< pos len) + (aset dst pos (logxor (aref str1 pos) (aref str2 pos))) + (setq pos (1+ pos))) + dst)) + +(defun scram-md5-make-client-msg-1 (authenticate-id &optional authorize-id) + "Make an initial client message from AUTHENTICATE-ID and AUTHORIZE-ID. +If AUTHORIZE-ID is the same as AUTHENTICATE-ID, it may be omitted." + (concat authorize-id "\0" authenticate-id "\0" (scram-make-unique-nonce))) + +(defun scram-md5-parse-server-msg-1 (server-msg-1) + "Parse SERVER-MSG-1 and return a list of (SALT SECURITY-INFO SERVICE-ID)." + (when (and (> (length server-msg-1) 16) + (eq (string-match "[^@]+@[^\0]+\0" server-msg-1 12) 12)) + (list (substring server-msg-1 0 8) ; salt + (substring server-msg-1 8 12) ; server-security-info + (substring server-msg-1 ; service-id + 12 (1- (match-end 0)))))) + +(defun scram-md5-make-salted-pass (passphrase salt) + (unwind-protect + (hmac-md5 salt passphrase) + ;; immediately erase plaintext passphrase from memory. + (fillarray passphrase 0))) + +(defun scram-md5-make-client-key (salted-pass) + (md5-binary salted-pass)) + +(defun scram-md5-make-client-verifier (client-key) + (md5-binary client-key)) + +(defun scram-md5-make-shared-key (server-msg-1 + client-msg-1 + client-security-info + client-verifier) + (hmac-md5 (concat server-msg-1 client-msg-1 client-security-info) + client-verifier)) + +(defun scram-md5-make-client-proof (client-key shared-key) + (scram-xor-string client-key shared-key)) + +(defun scram-md5-make-client-msg-2 (client-security-info client-proof) + (concat client-security-info client-proof)) + +(defun scram-md5-authenticate-server (server-msg-1 + server-msg-2 + client-msg-1 + client-security-info + salt salted-pass) + (string= (hmac-md5 (concat client-msg-1 server-msg-1 client-security-info) + (hmac-md5 salt salted-pass)) + server-msg-2)) + +(provide 'scram-md5) + +;;; scram-md5.el ends here