home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1997 December / Internet_Info_CD-ROM_Walnut_Creek_December_1997.iso / drafts / draft_n_r / draft-newman-auth-scram-01.txt < prev    next >
Text File  |  1997-10-06  |  48KB  |  1,347 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Network Working Group                                          C. Newman
  8. Internet Draft: SCRAM-MD5 SASL Mechanism                        Innosoft
  9. Document: draft-newman-auth-scram-01.txt                    October 1997
  10.                                                    Expires in six months
  11.  
  12.  
  13.        Salted Challenge Response Authentication Mechanism (SCRAM)
  14.  
  15.  
  16. Status of this memo
  17.  
  18.      This document is an Internet-Draft.  Internet-Drafts are working
  19.      documents of the Internet Engineering Task Force (IETF), its areas,
  20.      and its working groups.  Note that other groups may also distribute
  21.      working documents as Internet-Drafts.
  22.  
  23.      Internet-Drafts are draft documents valid for a maximum of six
  24.      months and may be updated, replaced, or obsoleted by other
  25.      documents at any time.  It is inappropriate to use Internet-Drafts
  26.      as reference material or to cite them other than as "work in
  27.      progress."
  28.  
  29.      To view the entire list of current Internet-Drafts, please check
  30.      the "1id-abstracts.txt" listing contained in the Internet-Drafts
  31.      Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net
  32.      (Europe), munnari.oz.au (Pacific Rim), ds.internic.net (US East
  33.      Coast), or ftp.isi.edu (US West Coast).
  34.  
  35.  
  36. Abstract
  37.  
  38.      SCRAM is a simple passphrase-based authentication mechanism
  39.      suitable for a wide variety of usage scenarios.  It combines the
  40.      best properties of CRAM-MD5 [CRAM-MD5] and OTP [OTP] without a
  41.      significant increase in complexity.
  42.  
  43.      This document defines the SCRAM-MD5 SASL mechanism [SASL] using the
  44.      MD5 [MD5] and HMAC-MD5 [HMAC] algorithms.  It is suitable for use
  45.      directly with protocols such as IMAP [IMAP4] and POP [POP3].
  46.  
  47.  
  48. 0. Changes from Previous Version
  49.  
  50.      (1) MD5 is used instead of SHA1 as it permits backwards-
  51.      compatibility with CRAM-MD5 verifiers on the server and it is a
  52.      more commonly available hash function.  This should not effect
  53.      SCRAM's security significantly.
  54.  
  55.  
  56.  
  57.  
  58. Newman                                                          [Page 1]
  59.  
  60. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  61.  
  62.  
  63.      (2) The server-proof is now independent of the client-verifier.
  64.      This allows a remote authentication service to efficiently restrict
  65.      the services an application server may offer to clients.
  66.  
  67.      (3) The salt is included in the client-key which means that a
  68.      compromised verifier and client-server exchange only gains access
  69.      to services which use the same salt.
  70.  
  71.      (4) The service identifier is simplified and separated from the
  72.      extension data which now has defined syntax.
  73.  
  74.      (5) The client-nonce may be omitted for one-way authentication.
  75.  
  76.      (6) Examples and sample source code has been added.
  77.  
  78.  
  79. 1. How to Read This Document
  80.  
  81.      This document has information for several different audiences.
  82.      Section 2 describes the highlights of SCRAM.  Sections 3-6 are
  83.      intended for implementors.  Section 7 is intended for system
  84.      administrators.  Sections 7-10 are intended for security
  85.      evaluation.
  86.  
  87.      The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
  88.      in this document are to be interpreted as defined in "Key words for
  89.      use in RFCs to Indicate Requirement Levels" [KEYWORDS].
  90.  
  91.  
  92. 2. SCRAM Highlights
  93.  
  94.      SCRAM is a simple passphrase-based mechanism, which does not
  95.      require complicated public key technology.  It can be implemented
  96.      in a few pages of source code.
  97.  
  98.      SCRAM is not plaintext equivalent, so it improves network security
  99.      over plaintext mechanisms without sacrificing security of the
  100.      authentication database.
  101.  
  102.      SCRAM includes a salt to prevent global dictionary attacks on the
  103.      server's authentication database.
  104.  
  105.      SCRAM supports proxy authentication by including an authorization
  106.      identity (user to login as) separate from the authentication
  107.      identity (server authentication database entry to use).
  108.  
  109.      SCRAM supports optional mutual authentication.
  110.  
  111.  
  112.  
  113.  
  114. Newman                                                          [Page 2]
  115.  
  116. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  117.  
  118.  
  119.      SCRAM supports limited server trust.  This means a centralized
  120.      authentication server can restrict the services offered by
  121.      application servers.
  122.  
  123.      SCRAM-MD5 is backwards-compatible with existing CRAM-MD5 verifiers
  124.      stored in server authentication databases.
  125.  
  126.  
  127. 3. Client Implementation of SCRAM-MD5
  128.  
  129.      This section includes a step-by-step guide for client implementors.
  130.      Although section 6 contains the formal definition of the syntax and
  131.      is the authoritative reference in case of errors here, this section
  132.      should be sufficient to build a correct implementation.
  133.  
  134.      When used with SASL the mechanism name is "SCRAM-MD5".  The
  135.      mechanism does not provide a security layer.
  136.  
  137.      The client begins by sending a message to the server containing the
  138.      following three pieces of information.  The entire message MUST NOT
  139.      exceed 1000 characters.
  140.  
  141.      (1) An authorization identity.  When the empty string is used, this
  142.      defaults to the authentication identity.  This is used by system
  143.      administrators or proxy servers to login with a different user
  144.      identity.  This field may be up to 255 octets and is terminated by
  145.      a NUL (0) octet.  US-ASCII printable characters are preferred,
  146.      although UTF-8 [UTF-8] printable characters are permitted to
  147.      support international names.  Use of character sets other than
  148.      US-ASCII and UTF-8 is forbidden.
  149.  
  150.      (2) An authentication identity.  The identity whose passphrase will
  151.      be used.  This field may be up to 255 octets and is terminated by a
  152.      NUL (0) octet.  US-ASCII printable characters are preferred,
  153.      although UTF-8 [UTF-8] printable characters are permitted to
  154.      support international names.  Use of character sets other than
  155.      US-ASCII and UTF-8 is forbidden.
  156.  
  157.      (3) An optional "client nonce."  If this is omitted, it indicates a
  158.      desire for client-only authentication.  When present, it is
  159.      important that this be globally unique.  One common technique for
  160.      generating globally unique identifiers combines a process
  161.      identifier with the system clock, a sequence number, a random
  162.      number and the client's domain name.  The random number is
  163.      important as clocks are often synchronized using insecure
  164.      protocols.  Advice for generating strong random numbers can be
  165.      found in [RANDOM].
  166.  
  167.  
  168.  
  169.  
  170. Newman                                                          [Page 3]
  171.  
  172. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  173.  
  174.  
  175.      The server responds by sending a message containing three pieces of
  176.      information.  The entire message MUST NOT exceed 1000 characters.
  177.  
  178.      (4) An 8-octet salt value, specific to the authentication identity.
  179.  
  180.      (5) A service id consisting of the service name of the protocol's
  181.      SASL profile followed by an "@" followed by the domain name of the
  182.      server and terminated by NUL.  The client SHOULD verify this is
  183.      correct.
  184.  
  185.      (6) A string containing extension data, terminated by NUL.  A
  186.      client which supports TLS [TLS] or stronger SASL mechanisms can
  187.      check this to protect against an active downgrade attack.  A server
  188.      which supports TLS or stronger SASL mechanisms SHOULD advertise
  189.      them here.
  190.  
  191.      (7) A "server nonce".
  192.  
  193.      The client then does the following:
  194.  
  195.      (A) Create a buffer containing the user's passphrase.  The client
  196.      MUST support passphrases of at least 64 octets.  US-ASCII
  197.      characters are preferred, although UTF-8 characters are permitted.
  198.      Character sets other than UTF-8 MUST NOT be used.
  199.  
  200.      (B) Apply the HMAC-MD5 function with (A) as the key and the 8-octet
  201.      salt as the data, producing a 16-octet result.  Once this is done,
  202.      (A) SHOULD be erased from memory.
  203.  
  204.      (C) Apply the MD5 function to the result of (B).  This produces a
  205.      16-octet result.
  206.  
  207.      (D) Apply the MD5 function to the result of (C).  This produces a
  208.      16-octet result.
  209.  
  210.      (E) Create a buffer containing the server's response (4)-(7),
  211.      immediately followed by the initial client message (1)-(3).
  212.  
  213.      (F) Apply the HMAC-MD5 function with the result of (D) as the key
  214.      and the buffer from (E) as the data.  This produces a 16-octet
  215.      result.
  216.  
  217.      (G) Create a 16-octet buffer containing the exclusive-or of (C) and
  218.      (F).
  219.  
  220.      The client then sends a message to the server containing the
  221.      following:
  222.  
  223.  
  224.  
  225.  
  226. Newman                                                          [Page 4]
  227.  
  228. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  229.  
  230.  
  231.      (8) The 16-octet result of step (G).
  232.  
  233.      If no client challenge was suppled in step 3, the one-way
  234.      authentication is now complete.
  235.  
  236.      (9) A 16-octet server authentication verifier.
  237.  
  238.      The client SHOULD verify this with the following procedure:
  239.  
  240.      (H) Apply the HMAC-MD5 function with the result of (B) as the key
  241.      and the 8-octet salt as the data.  This produces a 16-octet result.
  242.  
  243.      (I) Create a buffer containing the initial client message (1)-(3)
  244.      immediately followed by the initial server response (4)-(7).
  245.  
  246.      (J) Apply the HMAC-MD5 function with the result of (H) as the key
  247.      and the buffer from (I) as the data.
  248.  
  249.      (K) If the result of (J) matches (9), the server is authenticated.
  250.  
  251.      A secured client MAY store the result of (B) to re-authenticate to
  252.      services using the same salt, or the intermediate HMAC state from
  253.      (B) to re-authenticate to any service.  Clients SHOULD NOT store
  254.      the passphrase itself.
  255.  
  256.  
  257. 4. Server Implementation of SCRAM-MD5.
  258.  
  259.      The section includes a step-by-step guide for server implementors.
  260.      Although section 6 contains the formal definition of the syntax and
  261.      is the authoritative reference in case of errors here, this section
  262.      in conjunction with section 3 should be sufficient to build a
  263.      correct implementation.
  264.  
  265.      The server's authentication database contains an 8-octet salt, 16-
  266.      octet client verifier and a 16-octet server key for each local
  267.      user.  The server MUST support "user@host" syntax for the
  268.      authentication identity at least to the extent of stripping "@host"
  269.      when it matches the local hostname or rejecting the authentication
  270.      immediately after the initial client message if the hostname
  271.      doesn't match.  The server MAY support remote user authentication
  272.      using this syntax.
  273.  
  274.      The stored client verifier is equal to the result of step (D)
  275.      above, and the stored server key is equal to the result of step (J)
  276.      above.  To create its initial response, the server simply looks up
  277.      the authentication identity to fetch the salt, and generates an 8
  278.      to 248 octet nonce. This nonce MUST be unique to prevent replay
  279.  
  280.  
  281.  
  282. Newman                                                          [Page 5]
  283.  
  284. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  285.  
  286.  
  287.      attacks.  It can be generated by appending a system clock to a
  288.      random number [RANDOM].  To verify the client's credentials, the
  289.      server preforms the following steps:
  290.  
  291.      (a) Generate a buffer identical to step (E) above.
  292.  
  293.      (b) Apply the HMAC-MD5 function with the stored client verifier as
  294.      the key and the result of (a) as the data.  This produces a 16-
  295.      octet result equal to step (F) above.
  296.  
  297.      (c) Exclusive-or the result of (b) with message (8) from the
  298.      client.  This produces a 16-octet result which should be equal to
  299.      the result of step (C) above.
  300.  
  301.      (d) Apply the MD5 function to the output of step (c).  This
  302.      produces a 16-octet result which should be equal to the result of
  303.      step (D) above.
  304.  
  305.      (e) if the result of (d) is equal to the stored verifier, then the
  306.      user is authenticated.
  307.  
  308.      If no client challenge was provided in step (3), the server is now
  309.      done and responds with the appropriate status code.
  310.  
  311.      (f) Generate a buffer identical to step (I) above.
  312.  
  313.      (g) Apply the HMAC-MD5 function with the stored verifier as the key
  314.      and the buffer from (f) as the data.  This produces a 16-octet
  315.      result.
  316.  
  317.      The result of (g) is sent to the client to authenticate the server.
  318.  
  319.  
  320. 5. Example
  321.  
  322.      The following is an example of the SCRAM-MD5 mechanism using the
  323.      IMAP [IMAP4] profile of SASL.  Note that base64 encoding and the
  324.      lack of an initial client reponse with the first command are
  325.      characteristics of the IMAP profile of SASL and not characteristics
  326.      of SASL or SCRAM-MD5.
  327.  
  328.      In this example, "C:" represents lines sent from the client to the
  329.      server and "S:" represents lines sent from the server to the
  330.      client.  The wrapped lines are for editorial clarity -- there are
  331.      no actual newlines in the middle of the messages.
  332.  
  333.        C: a001 AUTHENTICATE SCRAM-MD5
  334.        S: +
  335.  
  336.  
  337.  
  338. Newman                                                          [Page 6]
  339.  
  340. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  341.  
  342.  
  343.        C: AGNocmlzADxwNVIxZTBWTzNLdFZBNEZITDdudWRRQGVsZWFub3Iua
  344.           W5ub3NvZnQuY29tPg==
  345.        S: AeYw5Ugm+blpbWFwQGVsZWFub3IuaW5ub3NvZnQuY29tAAA8b1JNa
  346.           nFFekYvL1J5WnhFMlF2cDNzd0BlbGVhbm9yLmlubm9zb2Z0LmNvbT4=
  347.        C: 5cZpsA9pODOVwuNU1xmJHA==
  348.        S: a001 OK [vJ1FEfRHulPALMwSb/UC9g==] AUTHENTICATE completed
  349.  
  350.      For this example, the user "chris", with an empty authorization
  351.      identity is using the passphrase "secret stuff".  The client nonce
  352.      is "<p5R1e0VO3KtVA4FHL7nudQ@eleanor.innosoft.com>" and the server
  353.      nonce is "<oRMjqEzF//RyZxE2Qvp3sw@eleanor.innosoft.com>".  The
  354.      service identity is "imap@eleanor.innosoft.com" and the server
  355.      extension data is empty.  The salt, in hexidecimal, is "01e6 30e5
  356.      4826 f9b9".  The complete 40 octet verifier stored on the server,
  357.      in base64, is
  358.      "AeYw5Ugm+bkHTj2Ouau2II2etDOwYVEXkVsKPP0Q6pV9hbFaweymdg", and in
  359.      hexidecimal it is "01e6 30e5 4826 f9b9 074e 3d8e b9ab b620 8d9e
  360.      b433 b061 5117 915b 0a3c fd10 ea95 7d85 b15a c1ec a676".
  361.  
  362.  
  363. 6. Formal Syntax of SCRAM-MD5 Messages
  364.  
  365.      This is the formal syntactic definition of the client and server
  366.      messages.  This uses ABNF [ABNF] notation.
  367.  
  368.      client-msg-1     = [authorize-id] NUL authenticate-id NUL [nonce]
  369.                         ;; MUST NOT exceed 1000 octets
  370.  
  371.      server-msg-1     = salt service-id NUL server-ext-data NUL nonce
  372.                         ;; MUST NOT exceed 1000 octets
  373.  
  374.      client-msg-2     = client-proof
  375.  
  376.      server-msg-2     = server-proof
  377.  
  378.      passphrase       = *UTF8-SAFE
  379.                         ;; At least 64 octets MUST be supported
  380.  
  381.      authorize-id     = *UTF8-PRINT
  382.                         ;; No more than 255 octets
  383.  
  384.      authenticate-id  = *UTF8-PRINT
  385.                         ;; No more than 255 octets
  386.  
  387.      service-id       = service-name "@" server-domain
  388.  
  389.      service-name     = *US-ASCII-PRINT
  390.                         ;; a SASL/GSSAPI service name
  391.  
  392.  
  393.  
  394. Newman                                                          [Page 7]
  395.  
  396. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  397.  
  398.  
  399.      server-domain    = *US-ASCII-PRINT
  400.                         ;; an internet domain name
  401.  
  402.      server-ext-data  = *(sasl-mech-list / tls-avail / ext-list)
  403.  
  404.      sasl-mech-list   = "SASL:" *(CFWS sasl-mech) CRLF
  405.  
  406.      CFWS             = [CRLF] 1*SPACE
  407.  
  408.      sasl-mech        = 1*20(ALPHA / DIGIT / "-" / "_")
  409.  
  410.      tls-avail        = "TLS:" SPACE "yes"
  411.  
  412.      ext-list         = 1*UTF8PRINT ":" *(CFWS 1*UTF8PRINT) CRLF
  413.  
  414.      nonce            = 8*OCTET
  415.  
  416.      salt             = 8OCTET
  417.  
  418.      client-proof     = 16OCTET
  419.  
  420.      server-proof     = 16OCTET
  421.  
  422.      NUL              = %x00  ;; US-ASCII NUL character
  423.  
  424.      US-ASCII-SAFE    = %x01-09 / %x0B-0C / %x0E-7F
  425.                        ;; US-ASCII except CR, LF, NUL
  426.  
  427.      US-ASCII-PRINT   = %x20-7E
  428.                        ;; printable US-ASCII including SPACE
  429.  
  430.      UTF8-SAFE        = US-ASCII-SAFE / UTF8-1 / UTF8-2 / UTF8-3
  431.                           / UTF8-4 / UTF8-5
  432.  
  433.      UTF8-PRINT       = US-ASCII-PRINT / UTF8-1 / UTF8-2 / UTF8-3
  434.                           / UTF8-4 / UTF8-5
  435.  
  436.      UTF8-CONT        = %x80..BF
  437.  
  438.      UTF8-1           = %xC0..DF UTF8-CONT
  439.  
  440.      UTF8-2           = %xE0..EF 2UTF8-CONT
  441.  
  442.      UTF8-3           = %xF0..F7 3UTF8-CONT
  443.  
  444.      UTF8-4           = %xF8..FB 4UTF8-CONT
  445.  
  446.      UTF8-5           = %xFC..FD 5UTF8-CONT
  447.  
  448.  
  449.  
  450. Newman                                                          [Page 8]
  451.  
  452. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  453.  
  454.  
  455. 7. System Administrator Advice
  456.  
  457.      This section includes advice for system administrators using this
  458.      mechanism.
  459.  
  460.      SCRAM stores three pieces of information for each user: a salt, a
  461.      client verifier and server key.  The latter two are derived from
  462.      the salt and the user's passphrase.
  463.  
  464.      The salt prevents global dictionary attacks, similar to the salt
  465.      used in Unix /etc/passwd files.  As the 12 bits of salt in Unix
  466.      /etc/passwd has proved to be insufficient, SCRAM uses 64 bits of
  467.      salt.  See [SCHNEIER] for a good discussion of salt and dictionary
  468.      attacks.  In a multi-server site, security can be increased by
  469.      using a different salt on each server.
  470.  
  471.      Although the verifiers used by SCRAM-MD5 have roughly comparable
  472.      security to those used by current plaintext mechanisms (such as
  473.      Unix /etc/passwd), it is still very important to keep them secret.
  474.      Just as tools exist to try common passwords against Unix
  475.      /etc/passwd files, it is also possible to build such tools for
  476.      SCRAM-MD5.  In addition, once a SCRAM-MD5 verifier is stolen, a
  477.      passive (undetectable) evesdropper of that user logging in gains
  478.      the output of step (C) above, which is sufficient to impersonate
  479.      the user to all services with the same salt.  This is far better
  480.      than current plaintext mechanisms where a passive evesdropper
  481.      always recovers the user's password, but is still a serious
  482.      concern.
  483.  
  484.      Verifiers SHOULD be kept hidden from all users on the server.
  485.      Sites which distribute verifiers among multiple servers, SHOULD
  486.      encrypt them when distributing them.
  487.  
  488.      SCRAM-MD5 is only a good mechanism if passphrases are well chosen.
  489.      For this reason, implementations should use the term "passphrase"
  490.      rather than "password" and when a user's passphrase is set, site
  491.      policy restrictions should be applied.  A reasonable site policy
  492.      would require passphrases of at least 10 characters with at least
  493.      one non-alphanumeric character.
  494.  
  495.      SCRAM-MD5 doesn't protect the integrity or privacy of data
  496.      exchanged after authentication.  Use of TLS [TLS] or a stronger
  497.      SASL mechanism such as Kerberos is encouraged if this functionality
  498.      is needed.
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506. Newman                                                          [Page 9]
  507.  
  508. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  509.  
  510.  
  511. 8. SCRAM-MD5 Functional Notation
  512.  
  513.      This section is designed to provide a quick understanding of
  514.      SCRAM-MD5 for those who like functional notation.
  515.  
  516.      +         octet concatenation
  517.      XOR       the exclusive-or function
  518.      AU        is the authentication user identity (NUL terminated)
  519.      AZ        is the authorization user identity (NUL terminated)
  520.                if AZ is the same as AU, a single NUL is used instead.
  521.      service   is the name of the service and server (NUL terminated)
  522.      ext-attr  server extension attributes (NUL terminated)
  523.      pass      is the plaintext passphrase
  524.      H(x)      is a one-way hash function applied to "x", such as MD5
  525.      MAC(x,y)  is a message authentication code (MAC) such as HMAC-MD5
  526.                "y" is the key and "x" is the text signed by the key.
  527.      salt      is a per-user salt value the server stores
  528.      Us        is a unique nonce the server sends to the client
  529.      Uc        is a unique nonce the client sends to the server
  530.  
  531.      The following computed values are used in the exchange:
  532.  
  533.      client-chal     = AZ + AU + Uc
  534.      server-chal     = salt + service + ext-attr + Us
  535.      salted-pass     = MAC(salt, pass)
  536.      client-key      = H(salted-pass)
  537.      client-verifier = H(client-key)
  538.      shared-key      = MAC(server-chal + client-chal, client-verifier)
  539.      client-proof    = client-key XOR shared-key
  540.      server-key      = MAC(salt, salted-pass)
  541.      server-proof    = MAC(client-chal + server-chal, server-key)
  542.  
  543.      The SCRAM exchange is as follows:
  544.  
  545.      (1) client -> server: client-chal
  546.      (2) server -> client: server-chal
  547.      (3) client -> server: client-proof
  548.      (4) server -> client: server-proof
  549.  
  550.      The server stores the salt, client-verifier and server-key.  It
  551.      authenticates the client by computing:
  552.  
  553.        H(client-proof XOR shared-key)
  554.  
  555.      after step 3 and comparing it to the stored client-verifier.
  556.  
  557.      The client verifies the server by computing the server-proof
  558.      directly and comparing.
  559.  
  560.  
  561.  
  562. Newman                                                         [Page 10]
  563.  
  564. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  565.  
  566.  
  567. 9. Usage Scenarios
  568.  
  569.  
  570.      Single Sign-on
  571.           As with CRAM, the intermediate HMAC context from step (B) can
  572.           be used for a single sign-on client model.  SCRAM also adds
  573.           the ability to store the output of step (B) for the single
  574.           sign-on only to services with the same salt.  If expiration is
  575.           needed, it can be built into the single sign-on facility.
  576.           Kerberos is necessary if server-enforced expiration is needed.
  577.           OTP is necessary if expiration after a fixed number of
  578.           authentications is necessary.
  579.  
  580.      Simplicity
  581.           CRAM, SCRAM and OTP are all suitable for use in lightweight
  582.           clients or servers.  Kerberos and public key technology are
  583.           not simple enough.
  584.  
  585.      Frequent Authentications
  586.           Protocols such as IMAP or POP result in frequent
  587.           authentications by the same user.  OTP, by itself, is not
  588.           suitable for such services as the sequence needs to be reset.
  589.           OTP with OTP extended responses still does not permit
  590.           simulatanous connections by the same user.
  591.  
  592.      Location Independent User
  593.           SCRAM, CRAM and OTP are all suitable for users which move
  594.           between many clients.  Public key client authentication will
  595.           not be suitable for such uses until there is a worldwide smart
  596.           card standard.
  597.  
  598.      Scalability / Server Efficiency
  599.           CRAM and SCRAM are believed to be scalable to large numbers of
  600.           users.  OTP is less scalable due to the need to provide per-
  601.           user locking and update services to the authentication
  602.           database.
  603.  
  604.      Client Efficiency
  605.           SCRAM has about half the client efficiency of CRAM.  OTP's
  606.           client efficiency varies with the sequence number and it is
  607.           usually many times slower than SCRAM.  Public key systems are
  608.           even slower.
  609.  
  610.      Limited Server Trust
  611.           The server-key may be stored on a central SCRAM server which
  612.           limits the services an application server is permitted to
  613.           offer.  CRAM and OTP do not offer this functionality.
  614.  
  615.  
  616.  
  617.  
  618. Newman                                                         [Page 11]
  619.  
  620. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  621.  
  622.  
  623.      Multi-Vendor Scenarios
  624.           SCRAM does not require cooperation between multiple services
  625.           on the same server or multiple applications on the same
  626.           client.  This has proved to be a deployment problem for
  627.           Kerberos.
  628.  
  629.      Proxy Authentication
  630.           SCRAM supports proxy authentication by including a separate
  631.           authentication and authorization identifiers.  CRAM lacks this
  632.           facility.
  633.  
  634.  
  635. 10. Security Considerations
  636.  
  637.      Security considerations are discussed throughout this document.
  638.      The security considerations of MD5 [MD5] and HMAC [HMAC] also
  639.      apply.  SCRAM relies primarily on the one-way characteristic of MD5
  640.      and HMAC-MD5 for cryptographic security.
  641.  
  642.      An analysis of different attacks follows:
  643.  
  644.      Passive Network Attacks
  645.  
  646.      SCRAM is resistant to replay attacks as long as the appropriate
  647.      nonce is unique.
  648.  
  649.      SCRAM is not resistant to passive dictionary attacks.  User
  650.      education, passphrase setting policy and TLS [TLS] may be used to
  651.      protect against such attacks.
  652.  
  653.      SCRAM does not protect against session data evesdropping.  TLS
  654.      [TLS] may be used to protect against this.
  655.  
  656.      Active Network Attacks
  657.  
  658.      SCRAM protects against server impersonation with the optional
  659.      server authentication.  CRAM and OTP do not have this facility.
  660.  
  661.      SCRAM can protect against client impersonation by providing no
  662.      information beyond the salt to a client which fails verification.
  663.      Note that in order to prevent revealing the existance of a user to
  664.      such attackers, the server will have to invent consistant salt
  665.      between attempts and fail after the second client message.  One way
  666.      to do this would be to store a random secret and use
  667.      HMAC(user-name, random-secret) to generate consistant salt values.
  668.  
  669.      The server-ext-data may be used to protect against downgrade active
  670.      attacks (where the active attacker changes the advertised protocol
  671.  
  672.  
  673.  
  674. Newman                                                         [Page 12]
  675.  
  676. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  677.  
  678.  
  679.      security services).  CRAM and OTP do not have this facility.
  680.  
  681.      SCRAM protects against account hijacking by an active attacker.
  682.      Use of OTP extended response [OTP-EXT] to reset the sequence is
  683.      susceptible to account hijacking.
  684.  
  685.      SCRAM does not protect against connection hijacking or corruption.
  686.      TLS [TLS] or IPAUTH [IPAUTH] may be used to protect against this.
  687.  
  688.      SCRAM does not protect against active denial of service attacks.
  689.  
  690.      Server Attacks
  691.  
  692.      SCRAM verifiers by themselves can not be used to impersonate the
  693.      user.  CRAM verifiers have this weakness.
  694.  
  695.      An attacker which has access to both the SCRAM verifier and a
  696.      client exchange for a particular user gains the ability to
  697.      impersonate that user to other servers using the same salt.  TLS
  698.      [TLS] can make it more difficult to obtain the client exchange, but
  699.      does not defend against installation of a trojan horse server.
  700.  
  701.      Client Attacks
  702.  
  703.      As SCRAM is designed for user entry of a plaintext passphrase, it
  704.      is vulnerable to passphrase hijacking by trojan horse clients.  OTP
  705.      [OTP] with an independent OTP calculator can be used to limit the
  706.      vulnerability to a single session.
  707.  
  708.  
  709. 11. Intellectual Property Issues and Prior Art
  710.  
  711.      The author is not aware of any patents which apply to this
  712.      mechanism.
  713.  
  714.      This is primarily a derivative of simple hash-based challenge
  715.      response systems.  The hash-based challenge response idea has
  716.      existed since at least 1992, when the RIPE project published the
  717.      SKID algorithm according to [SCHNEIER].
  718.  
  719.      The repeated-hash idea used to verify the client's authenticator is
  720.      derived from S/KEY [SKEY].
  721.  
  722.      The idea of using salt to protect against global dictionary attacks
  723.      dates back to at least the Unix /etc/password system.  There is
  724.      some discussion of this in [SCHNEIER].
  725.  
  726.      SCRAM combines these techniques.  The author of this specification
  727.  
  728.  
  729.  
  730. Newman                                                         [Page 13]
  731.  
  732. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  733.  
  734.  
  735.      first proposed this on a public mailing list July 16, 1997.
  736.  
  737.  
  738. 12. References
  739.  
  740.      [ABNF] Crocker, D., "Augmented BNF for Syntax Specifications:
  741.      ABNF", Work in progress: draft-ietf-drums-abnf-xx.txt
  742.  
  743.      [CRAM-MD5] Klensin, Catoe, Krumviede, "IMAP/POP AUTHorize Extension
  744.      for Simple Challenge/Response", RFC 2195, MCI, September 1997.
  745.  
  746.          <ftp://ds.internic.net/rfc/rfc2195.txt>
  747.  
  748.      [HMAC] Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for Message
  749.      Authentication", RFC 2104, IBM, UCSD, February 1997.
  750.  
  751.          <ftp://ds.internic.net/rfc/rfc2104.txt>
  752.  
  753.      [IMAP4] Crispin, M., "Internet Message Access Protocol - Version
  754.      4rev1", RFC 2060, University of Washington, December 1996.
  755.  
  756.          <ftp://ds.internic.net/rfc/rfc2060.txt>
  757.  
  758.      [IPAUTH] Atkinson, "IP Authentication Header", RFC 1826, Naval
  759.      Research Laboratory, August 1995.
  760.  
  761.          <ftp://ds.internic.net/rfc/rfc1826.txt>
  762.  
  763.      [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate
  764.      Requirement Levels", RFC 2119, Harvard University, March 1997.
  765.  
  766.          <ftp://ds.internic.net/rfc/rfc2119.txt>
  767.  
  768.      [MD5] Rivest, "The MD5 Message Digest Algorithm", RFC 1321, MIT
  769.      Laboratory for Computer Science, April 1992.
  770.  
  771.          <ftp://ds.internic.net/rfc/rfc1321.txt>
  772.  
  773.      [OTP] Haller, Metz, "A One-Time Password System", RFC 1938,
  774.      Bellcore, Kaman Sciences Corporation, May 1996.
  775.  
  776.          <ftp://ds.internic.net/rfc/rfc1938.txt>
  777.  
  778.      [OTP-EXT] Metz, "OTP Extended Responses", work in progress.
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786. Newman                                                         [Page 14]
  787.  
  788. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  789.  
  790.  
  791.      [POP3] Myers, J., Rose, M., "Post Office Protocol - Version 3", RFC
  792.      1939, Carnegie Mellon, Dover Beach Consulting, Inc., May 1996.
  793.  
  794.              <ftp://ds.internic.net/rfc/rfc1939.txt>
  795.  
  796.      [RANDOM] Eastlake, Crocker, Schiller, "Randomness Recommendations
  797.      for Security", RFC 1750, DEC, Cybercash, MIT, December 1994.
  798.  
  799.          <ftp://ds.internic.net/rfc/rfc1750.txt>
  800.  
  801.      [SASL] Myers, "Simple Authentication and Security Layer (SASL)",
  802.      work in progress.
  803.  
  804.      [SCHNEIER] Schneier, "Applied Cryptography: Protocols, Algorithms
  805.      and Source Code in C," John Wiley and Sons, Inc., 1996.
  806.  
  807.      [SKEY] Haller, Neil M. "The S/Key One-Time Password System", RFC
  808.      1760, Bellcore, February 1995.
  809.  
  810.          <ftp://ds.internic.net/rfc/rfc1760.txt>
  811.  
  812.      [TLS] Dierks, Allen, "The TLS Protocol Version 1.0", Work in
  813.      progress.
  814.  
  815.      [UTF8] Yergeau, F. "UTF-8, a transformation format of Unicode and
  816.      ISO 10646", RFC 2044, Alis Technologies, October 1996.
  817.  
  818.          <ftp://ds.internic.net/rfc/rfc2044.txt>
  819.  
  820. 13. Author's Address
  821.  
  822.      Chris Newman
  823.      Innosoft International, Inc.
  824.      1050 Lakes Drive
  825.      West Covina, CA 91790 USA
  826.  
  827.      Email: chris.newman@innosoft.com
  828.  
  829. A. Appendix - TWEKE Proposal
  830.  
  831.      Tom Wu has proposed adding a Diffie-Hellman key exchange to this
  832.      mechanism.  Diffie-Hellman works roughly as follows:
  833.  
  834.      Server picks g, n and x.  Server computes X = g^x mod n.
  835.  
  836.      server -> client: g, n, X
  837.  
  838.      Client picks y and computes Y = g^y mod n  and  K = X^y mod n.
  839.  
  840.  
  841.  
  842. Newman                                                         [Page 15]
  843.  
  844. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  845.  
  846.  
  847.      client -> server: Y
  848.  
  849.      Server computes K = Y^x mod n  (which is the same as the client's
  850.      K).
  851.  
  852.      If g, n, x and y are sufficiently big and have the right
  853.      characteristics, then both the client and server share K which is
  854.      very difficult for a passive evesdropper to obtain.
  855.  
  856.      The TWEKE proposal would add the following steps:
  857.  
  858.      (4.5) Server sends g, n, X.
  859.  
  860.      (8.5) Client sends Y.
  861.  
  862.      and would modify steps (F), (J), (b) and (g) to include the value
  863.      K.  This would result in a protocol safe from passive network
  864.      attacks.  The expense would be reduced performance, the need for a
  865.      bignum math library and possibly a requirement that an export
  866.      license be obtained from certain governments (included the United
  867.      States).  This would not defend against active attacks unless an
  868.      encryption service was added.  This may be free of patent
  869.      restrictions.
  870.  
  871.      TWEKE would be harder to deploy than SCRAM due to the higher math,
  872.      the use of public key technology and the performance loss.
  873.  
  874. B. Appendix - Additional Services
  875.  
  876.      Several additional services are needed to make SCRAM useful in
  877.      various usage scenarios.  These include remote authentication
  878.      database support for servers, authentication database APIs for
  879.      servers, remote passphrase change support for clients,
  880.      single-sign-on APIs for clients and management tools.  The
  881.      service-id and server-key are included to facilite the remote
  882.      authentication database service.  Otherwise these issues are
  883.      deferred for future work.
  884.  
  885. C. Appendix - HMAC-MD5 Sample Source Code
  886.  
  887.      The following sample C source code is calls the source code in
  888.      [MD5] and is derived from the source code in [HMAC].  It is needed
  889.      by the SCRAM source code in the next section.
  890.  
  891.      /* hmac-md5.h -- HMAC-MD5 functions
  892.       */
  893.  
  894.      #define HMAC_MD5_SIZE 16
  895.  
  896.  
  897.  
  898. Newman                                                         [Page 16]
  899.  
  900. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  901.  
  902.  
  903.      /* intermediate MD5 context */
  904.      typedef struct HMAC_MD5_CTX_s {
  905.          MD5_CTX ictx, octx;
  906.      } HMAC_MD5_CTX;
  907.  
  908.      /* One step hmac computation
  909.       *
  910.       * digest may be same as text or key
  911.       */
  912.      void hmac_md5(const unsigned char *text, int text_len,
  913.                    const unsigned char *key, int key_len,
  914.                    unsigned char digest[HMAC_MD5_SIZE]);
  915.  
  916.      /* create intermediate result from key
  917.       */
  918.      void hmac_md5_init(HMAC_MD5_CTX *hmac,
  919.                         const unsigned char *key, int key_len);
  920.  
  921.      #define hmac_md5_update(hmac, text, text_len) \
  922.        MD5Update(&(hmac)->ictx, (text), (text_len))
  923.  
  924.      /* finish hmac from intermediate result.
  925.       * Intermediate result is zeroed.
  926.       */
  927.      void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
  928.                          HMAC_MD5_CTX *hmac);
  929.  
  930.  
  931.  
  932.      /* hmac-md5.c -- Keyed-Hashing
  933.       *  derived from RFC 2104 by H. Krawczyk, M. Bellare, R.Canetti
  934.       */
  935.  
  936.      #include <stdio.h>
  937.      #include <string.h>
  938.      #include "md5.h"
  939.      #include "hmac-md5.h"
  940.  
  941.      /* MD5 block size */
  942.      #define BLOCK_SIZE 64
  943.  
  944.      void hmac_md5_init(HMAC_MD5_CTX *hmac,
  945.                         const unsigned char *key, int key_len)
  946.      {
  947.          unsigned char k_pad[BLOCK_SIZE];    /* padded key */
  948.          int i;
  949.  
  950.  
  951.  
  952.  
  953.  
  954. Newman                                                         [Page 17]
  955.  
  956. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  957.  
  958.  
  959.          /* if key longer than BLOCK_SIZE bytes reset it to MD5(key) */
  960.          if (key_len > BLOCK_SIZE) {
  961.              MD5Init(&hmac->ictx);
  962.              MD5Update(&hmac->ictx, key, key_len);
  963.              MD5Final(k_pad, &hmac->ictx);
  964.              key = k_pad;
  965.              key_len = HMAC_MD5_SIZE;
  966.          }
  967.  
  968.          /* XOR padded key with inner pad value */
  969.          for (i = 0; i < key_len; i++) {
  970.              k_pad[i] = key[i] ^ 0x36;
  971.          }
  972.          while (i < BLOCK_SIZE) {
  973.              k_pad[i++] = 0x36;
  974.          }
  975.  
  976.          /* Begin inner MD5 */
  977.          MD5Init(&hmac->ictx);
  978.          MD5Update(&hmac->ictx, k_pad, BLOCK_SIZE);
  979.  
  980.          /* XOR padded key with outer pad value */
  981.          for (i = 0; i < BLOCK_SIZE; ++i) {
  982.              k_pad[i] ^= (0x36 ^ 0x5c);
  983.          }
  984.  
  985.          /* Begin outer MD5 */
  986.          MD5Init(&hmac->octx);
  987.          MD5Update(&hmac->octx, k_pad, BLOCK_SIZE);
  988.  
  989.          /* clean up workspace */
  990.          memset(k_pad, 0, BLOCK_SIZE);
  991.      }
  992.  
  993.      void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
  994.                          HMAC_MD5_CTX *hmac)
  995.      {
  996.          /* finish inner MD5 */
  997.          MD5Final(digest, &hmac->ictx);
  998.          /* finish outer MD5 */
  999.          MD5Update(&hmac->octx, digest, HMAC_MD5_SIZE);
  1000.          MD5Final(digest, &hmac->octx);
  1001.          /* MD5Final zeros context */
  1002.      }
  1003.  
  1004.      void hmac_md5(const unsigned char *text, int text_len,
  1005.                    const unsigned char *key, int key_len,
  1006.                    unsigned char digest[HMAC_MD5_SIZE])
  1007.  
  1008.  
  1009.  
  1010. Newman                                                         [Page 18]
  1011.  
  1012. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1013.  
  1014.  
  1015.      {
  1016.          HMAC_MD5_CTX hmac;
  1017.  
  1018.          hmac_md5_init(&hmac, key, key_len);
  1019.          hmac_md5_update(&hmac, text, text_len);
  1020.          hmac_md5_final(digest, &hmac);
  1021.      }
  1022.  
  1023.  
  1024. D. Appendix - SCRAM sample source code
  1025.  
  1026.      The following sample source code implements SCRAM itself for both
  1027.      server and client.
  1028.  
  1029.      Please note the comments marked "/*XXX ... */" as they need to be
  1030.      translated from English to computer readable code.
  1031.  
  1032.      A client implementation simply calls scram_md5_generate() with the
  1033.      passphrase after receiving the first server reply.  The cproof
  1034.      parameter will hold the message to send to the server and the
  1035.      sproof parameter will hold the expected server mutual
  1036.      authentication.  A client may also call cram_md5_cred() to turn a
  1037.      passphrase into CRAM/SCRAM credentials for later use in
  1038.      scram_md5_generate().
  1039.  
  1040.      A server implementation simply calls scram_md5_generate() with the
  1041.      stored verifier, the second client message and the SCRAM_VERIFY
  1042.      option.  Server verifiers are generated by creating a random salt
  1043.      and calling scram_md5_vgen() with either the passphrase or
  1044.      CRAM/SCRAM credentials.
  1045.  
  1046.      /* scram.h -- scram utility functions
  1047.       */
  1048.  
  1049.      /* size of CRAM_MD5 verifier and CRAM_MD5/SCRAM_MD5 credentials */
  1050.      #define CRAM_MD5_SIZE 32
  1051.  
  1052.      /* size of SCRAM_MD5 salt and verifier */
  1053.      #define SCRAM_MD5_SALTSIZE 8
  1054.      #define SCRAM_MD5_DATASIZE 16
  1055.  
  1056.      /* SCRAM verifier */
  1057.      typedef struct SCRAM_MD5_VRFY_s {
  1058.          unsigned char salt[SCRAM_MD5_SALTSIZE];
  1059.          unsigned char clidata[SCRAM_MD5_DATASIZE];
  1060.          unsigned char svrdata[SCRAM_MD5_DATASIZE];
  1061.      } SCRAM_MD5_VRFY;
  1062.  
  1063.  
  1064.  
  1065.  
  1066. Newman                                                         [Page 19]
  1067.  
  1068. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1069.  
  1070.  
  1071.      /* prepare CRAM-MD5 credentials/verifier also SCRAM-MD5 credential
  1072.       *  buf       -- must be aligned and have room for CRAM_MD5_SIZE
  1073.       *  pass      -- passphrase or verifier
  1074.       *  passlen   -- len of pass/verifier (0 ok if NUL terminated)
  1075.       */
  1076.      void cram_md5_cred(char *buf, const char *pass, int passlen);
  1077.  
  1078.      /* generate SCRAM-MD5 verifier
  1079.       *  vptr      -- gets result
  1080.       *  salt      -- contains salt of SCRAM_MD5_SALTSIZE
  1081.       *  pass      -- passphrase or verifier
  1082.       *  passlen   -- len of pass/verifier (0 ok if NUL terminated)
  1083.       *  plainflag -- 1 = plaintext passphrase,
  1084.       *               0 = result of cram_md5_cred()
  1085.       *  clientkey -- cache for client proof, usually NULL
  1086.       */
  1087.      void scram_md5_vgen(SCRAM_MD5_VRFY *vptr,
  1088.                          const unsigned char *salt,
  1089.                          const char *pass, int passlen, int plainflag,
  1090.                          unsigned char *clientkey);
  1091.  
  1092.      /* scram secret action type
  1093.       */
  1094.      #define SCRAM_CREDENTIAL 0 /* generate replies using credentials */
  1095.      #define SCRAM_PLAINTEXT  1 /* generate replies using plaintext */
  1096.      #define SCRAM_VERIFY     2 /* use SCRAM_MD5_VRFY to verify client,
  1097.                                    and generate server reply */
  1098.  
  1099.      /* generate or verify SCRAM-MD5
  1100.       * input params:
  1101.       *  cchal     -- client challenge string
  1102.       *  cchallen  -- length of client challenge
  1103.       *  schal     -- server challenge string
  1104.       *  schallen  -- length of server challenge
  1105.       *  secret    -- passphrase, credentials or verifier
  1106.       *  secretlen -- length of passphrase (0 ok if NUL terminated)
  1107.       *  action    -- see above
  1108.       * in/out:
  1109.       *  cproof    -- client proof of length SCRAM_MD5_DATASIZE
  1110.       * output:
  1111.       *  sproof    -- server proof of length SCRAM_MD5_DATASIZE
  1112.       * returns:
  1113.       *  -2 if params invalid
  1114.       *  -1 if verify fails
  1115.       *   0 on success
  1116.       */
  1117.      int scram_md5_generate(const char *cchal, int cchallen,
  1118.                             const char *schal, int schallen,
  1119.  
  1120.  
  1121.  
  1122. Newman                                                         [Page 20]
  1123.  
  1124. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1125.  
  1126.  
  1127.                             const char *secret, int secretlen,
  1128.                             int action, unsigned char *cproof,
  1129.                             unsigned char *sproof);
  1130.  
  1131.  
  1132.      /* scram.c -- routines for SCRAM-MD5 calculations
  1133.       */
  1134.  
  1135.      #include <stdio.h>
  1136.      #include <stdlib.h>
  1137.      #include <string.h>
  1138.      #include "md5.h"
  1139.      #include "hmac-md5.h"
  1140.      #include "scram.h"
  1141.  
  1142.      /* for htonl() and ntohl() */
  1143.      #include <sys/types.h>
  1144.      #include <netinet/in.h>
  1145.  
  1146.      /* MD5 block size */
  1147.      #define BLOCK_SIZE 64
  1148.  
  1149.      /* intermediate CRAM context
  1150.       *  values stored in network byte order (Big Endian)
  1151.       */
  1152.      typedef struct CRAM_MD5_CTX_s {
  1153.          UINT4 istate[4];
  1154.          UINT4 ostate[4];
  1155.      } CRAM_MD5_CTX;
  1156.  
  1157.      void cram_md5_cred(char *buf, const char *pass, int passlen)
  1158.      {
  1159.          HMAC_MD5_CTX hctx;
  1160.          CRAM_MD5_CTX *ctx = (CRAM_MD5_CTX *) buf;
  1161.  
  1162.          if (passlen == 0) passlen = strlen(pass);
  1163.          hmac_md5_init(&hctx, (const unsigned char *) pass, passlen);
  1164.          ctx->istate[0] = htonl(hctx.ictx.state[0]);
  1165.          ctx->istate[1] = htonl(hctx.ictx.state[1]);
  1166.          ctx->istate[2] = htonl(hctx.ictx.state[2]);
  1167.          ctx->istate[3] = htonl(hctx.ictx.state[3]);
  1168.          ctx->ostate[0] = htonl(hctx.octx.state[0]);
  1169.          ctx->ostate[1] = htonl(hctx.octx.state[1]);
  1170.          ctx->ostate[2] = htonl(hctx.octx.state[2]);
  1171.          ctx->ostate[3] = htonl(hctx.octx.state[3]);
  1172.          memset(&hctx, 0, sizeof (hctx));
  1173.      }
  1174.  
  1175.  
  1176.  
  1177.  
  1178. Newman                                                         [Page 21]
  1179.  
  1180. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1181.  
  1182.  
  1183.      /* extract hmac context from CRAM-MD5 credentials
  1184.       */
  1185.      void hmac_cram_md5_init(HMAC_MD5_CTX *hctx, CRAM_MD5_CTX *ctx)
  1186.      {
  1187.          hctx->ictx.state[0] = ntohl(ctx->istate[0]);
  1188.          hctx->ictx.state[1] = ntohl(ctx->istate[1]);
  1189.          hctx->ictx.state[2] = ntohl(ctx->istate[2]);
  1190.          hctx->ictx.state[3] = ntohl(ctx->istate[3]);
  1191.          hctx->octx.state[0] = ntohl(ctx->ostate[0]);
  1192.          hctx->octx.state[1] = ntohl(ctx->ostate[1]);
  1193.          hctx->octx.state[2] = ntohl(ctx->ostate[2]);
  1194.          hctx->octx.state[3] = ntohl(ctx->ostate[3]);
  1195.          hctx->ictx.count[0] = hctx->octx.count[0] = BLOCK_SIZE << 3;
  1196.          hctx->ictx.count[1] = hctx->octx.count[1] = 0;
  1197.      }
  1198.  
  1199.      void scram_md5_vgen(SCRAM_MD5_VRFY *vptr,
  1200.                          const unsigned char *salt,
  1201.                          const char *pass, int passlen, int plainflag,
  1202.                          unsigned char *clientkey)
  1203.      {
  1204.          HMAC_MD5_CTX hctx;
  1205.  
  1206.          if (clientkey == NULL) clientkey = vptr->clidata;
  1207.  
  1208.          /* get context */
  1209.          if (plainflag) {
  1210.              if (passlen == 0) passlen = strlen(pass);
  1211.              hmac_md5_init(&hctx, (const unsigned char *) pass,
  1212.                            passlen);
  1213.          } else {
  1214.              hmac_cram_md5_init(&hctx, (CRAM_MD5_CTX *) pass);
  1215.          }
  1216.  
  1217.          /* generate salted passphrase */
  1218.          hmac_md5_update(&hctx, salt, SCRAM_MD5_SALTSIZE);
  1219.          hmac_md5_final(vptr->clidata, &hctx);
  1220.  
  1221.          /* generate server proof */
  1222.          hmac_md5(salt, SCRAM_MD5_SALTSIZE, vptr->clidata,
  1223.                   sizeof (vptr->clidata), vptr->svrdata);
  1224.  
  1225.          /* generate client key and client verifier */
  1226.          MD5Init(&hctx.ictx);
  1227.          MD5Update(&hctx.ictx, vptr->clidata, sizeof (vptr->clidata));
  1228.          MD5Final(clientkey, &hctx.ictx);
  1229.          MD5Init(&hctx.ictx);
  1230.          MD5Update(&hctx.ictx, clientkey, SCRAM_MD5_DATASIZE);
  1231.  
  1232.  
  1233.  
  1234. Newman                                                         [Page 22]
  1235.  
  1236. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1237.  
  1238.  
  1239.          MD5Final(vptr->clidata, &hctx.ictx);
  1240.  
  1241.          /* copy salt to verifier */
  1242.          if (salt != vptr->salt) {
  1243.              memcpy(vptr->salt, salt, SCRAM_MD5_SALTSIZE);
  1244.          }
  1245.      }
  1246.  
  1247.      int scram_md5_generate(const char *cchal, int cchallen,
  1248.                             const char *schal, int schallen,
  1249.                             const char *secret, int secretlen,
  1250.                             int action, unsigned char *cproof,
  1251.                             unsigned char *sproof)
  1252.      {
  1253.          SCRAM_MD5_VRFY verifier, *vptr;
  1254.          HMAC_MD5_CTX hctx;
  1255.          unsigned char clientkey[HMAC_MD5_SIZE];
  1256.          unsigned char sharedkey[HMAC_MD5_SIZE];
  1257.          int i, result = 0;
  1258.  
  1259.          /* check params */
  1260.          if ((action == SCRAM_CREDENTIAL && secretlen != CRAM_MD5_SIZE)
  1261.              || (action == SCRAM_VERIFY
  1262.                  && secretlen != sizeof (verifier))
  1263.              || schallen < SCRAM_MD5_SALTSIZE) {
  1264.              return (-2);
  1265.          }
  1266.  
  1267.          /* get verifier */
  1268.          if (action == SCRAM_VERIFY) {
  1269.              vptr = (SCRAM_MD5_VRFY *) secret;
  1270.          } else {
  1271.              scram_md5_vgen(&verifier, (const unsigned char *) schal,
  1272.                             secret, secretlen, action, clientkey);
  1273.              vptr = &verifier;
  1274.          }
  1275.  
  1276.          /* calculate shared key */
  1277.          hmac_md5_init(&hctx, vptr->clidata, sizeof (vptr->clidata));
  1278.          hmac_md5_update(&hctx, (unsigned char *) schal, schallen);
  1279.          hmac_md5_update(&hctx, (unsigned char *) cchal, cchallen);
  1280.          hmac_md5_final(sharedkey, &hctx);
  1281.  
  1282.          if (action == SCRAM_VERIFY) {
  1283.              /* verify client proof */
  1284.              for (i = 0; i < HMAC_MD5_SIZE; ++i) {
  1285.                  /*XXX: the line which belongs here is omitted due to U.S.
  1286.                    export regulations, but it exclusive-ors the
  1287.  
  1288.  
  1289.  
  1290. Newman                                                         [Page 23]
  1291.  
  1292. Internet Draft          SCRAM-MD5 SASL Mechanism            October 1997
  1293.  
  1294.  
  1295.                    "sharedkey" with the "cproof" and places the result in
  1296.                    "clientkey" (see step (c) above) */
  1297.              }
  1298.              MD5Init(&hctx.ictx);
  1299.              MD5Update(&hctx.ictx, clientkey, sizeof (clientkey));
  1300.              MD5Final(clientkey, &hctx.ictx);
  1301.              if (memcmp(clientkey, vptr->clidata,
  1302.                         sizeof (clientkey)) != 0) {
  1303.                  result = -1;
  1304.              }
  1305.          } else {
  1306.              /* generate client proof */
  1307.              for (i = 0; i < HMAC_MD5_SIZE; ++i) {
  1308.                  /*XXX: the line which belongs here is omitted due to U.S.
  1309.                    export regulations, but it exclusive-ors the
  1310.                    "sharedkey" with the "clientkey" and places the result
  1311.                    in "cproof" (see step (G) above) */
  1312.              }
  1313.          }
  1314.  
  1315.          /* calculate server result */
  1316.          if (result == 0) {
  1317.              hmac_md5_init(&hctx, vptr->svrdata, HMAC_MD5_SIZE);
  1318.              hmac_md5_update(&hctx, (unsigned char *) schal, schallen);
  1319.              hmac_md5_update(&hctx, (unsigned char *) cchal, cchallen);
  1320.              hmac_md5_final(sproof, &hctx);
  1321.          }
  1322.  
  1323.          /* cleanup workspace */
  1324.          memset(clientkey, 0, sizeof (clientkey));
  1325.          memset(sharedkey, 0, sizeof (sharedkey));
  1326.          if (vptr == &verifier) memset(&verifier, 0, sizeof (verifier));
  1327.  
  1328.          return (result);
  1329.      }
  1330.  
  1331.  
  1332.  
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346. Newman                                                         [Page 24]
  1347.