Initial release, version 0.0.0.
[gsasl.git] / doc / specification / draft-newman-auth-scram-03.txt
blobba8ebe81b3bd49338cefc2dfd8134b945b9ebeb2
6 Network Working Group                                          C. Newman
7 Internet Draft: SCRAM-MD5 SASL Mechanism                        Innosoft
8 Document: draft-newman-auth-scram-03.txt                      March 1998
9                                                    Expires in six months
12        Salted Challenge Response Authentication Mechanism (SCRAM)
15 Status of this memo
17      This document is an Internet-Draft.  Internet-Drafts are working
18      documents of the Internet Engineering Task Force (IETF), its areas,
19      and its working groups.  Note that other groups may also distribute
20      working documents as Internet-Drafts.
22      Internet-Drafts are draft documents valid for a maximum of six
23      months and may be updated, replaced, or obsoleted by other
24      documents at any time.  It is inappropriate to use Internet-Drafts
25      as reference material or to cite them other than as "work in
26      progress."
28      To view the entire list of current Internet-Drafts, please check
29      the "1id-abstracts.txt" listing contained in the Internet-Drafts
30      Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net
31      (Europe), munnari.oz.au (Pacific Rim), ds.internic.net (US East
32      Coast), or ftp.isi.edu (US West Coast).
35 Abstract
37      SCRAM is a simple passphrase-based SASL [SASL] authentication
38      mechanism suitable for a wide variety of usage scenarios.  It
39      combines good properties of CRAM-MD5 [CRAM-MD5] and OTP [OTP], adds
40      some management features and some protection from active attacks
41      without a significant increase in complexity.  SCRAM is intended
42      for use with services which need a simple, fast and flexible
43      authentication mechanism.
45      [NOTE: Public discussion of this mechanism may take place on the
46      ietf-sasl@imc.org mailing list with a subscription address of
47      ietf-sasl-request@imc.org.  Private comments may be sent to the
48      author].
51 1. How to Read This Document
53      This document has information for several different audiences.
57 Newman                                                          [Page 1]
59 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
62      Section 2 provides an introduction to SCRAM.  Sections 3-6 and 9
63      are intended for implementors.  Section 7 is intended for system
64      administrators.  Sections 7-10 are intended for security
65      evaluation.
67      The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT" and "MAY"
68      in this document are to be interpreted as defined in "Key words for
69      use in RFCs to Indicate Requirement Levels" [KEYWORDS].
72 2. Introduction
74      This section describes the design goals, an overview of how SCRAM
75      operates and the intended use of SCRAM in comparison to OTP.
78 2.1. Design Goals
80      The perfect authentication mechanism would be simple, fast, strong,
81      use publicly available source code and be backwards compatible with
82      deployed back-end authentication databases.  It is impossible to
83      achieve all these goals so tradeoffs must be made.  SCRAM has
84      simplicity, speed and protection from passive and active attacks on
85      the connection (with the exception of dictionary attacks) as
86      primary design goals.  It has managability, backwards compatibility
87      with CRAM-MD5 intermediate HMAC state verifiers, some protection
88      from a compromised authentication database and publicly
89      distributable source code as secondary design goals.
91      SCRAM has the following characteristics:
93      o  It is a simple passphrase-based mechanism which does not require
94         complicated infrastructures or public key technology.  The
95         majority of the source code necessary to implement SCRAM is
96         included in the MD5 specification [MD5] and Appendices B and C
97         of this specification.
99      o  It does not require plain-text-equivalent verifiers on the
100         server, so it improves network security over traditional
101         plain-text password systems without eliminating security of the
102         server authentication database.
104      o  It supports proxy authentication by including an authorization
105         identity (user to login as) separate from the authentication
106         identity (server authentication database entry to use).
108      o  It supports mutual authentication.
113 Newman                                                          [Page 2]
115 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
118      o  It supports a limited service trust management model.  This
119         means a centralized authentication server could restrict the
120         services offered by application servers.
122      o  It is backwards-compatible with CRAM-MD5 server authentication
123         databases.
125      o  It includes an optional SASL integrity protection layer for
126         lightweight protection from many active attacks.
129 2.2. Basic Operation of SCRAM
131      SCRAM is built using only a simple one-way hash function, the HMAC
132      [HMAC] construction and the exclusive-or operation.  There are
133      three fundamental components to the exchange:
135      o  the client key which is derived from the passphrase and salt
137      o  the client verifier which is simply the one-way hash function
138         applied to the client key
140      o  the server key which is also derived from the passphrase and
141         salt
143      The server has access to the salt, client verifier and server key
144      for each user.  The salt and client verifier are used to
145      authenticate the client to the server and the salt and server key
146      are used to authenticate the server to the client.
148      The mechanism relies on the one-way characteristic of the hash
149      function to assure that the client key can't be derived from the
150      client verifier and that the server key can't be derived from
151      either the client key or client verifier.
153      SCRAM uses HMAC to sign client and server nonces with the client
154      verifier to produce a shared key.  The client exclusive-ors the
155      shared key with the client key and sends that to the server which
156      uses the shared key to reverse the exclusive-or operation, extract
157      the client key, and then verify that the hash function applied to
158      the client key matches the client verifier.  The server uses HMAC
159      to sign the client and server nonces with the server key and sends
160      that to the client to authenticate.
162 2.3. Intended Use
164      SCRAM is designed for a usage scenario where simplicity and/or
165      speed is important, frequent authentications may occur and the
169 Newman                                                          [Page 3]
171 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
174      primary threat is passive and active network attacks.  A good
175      example of protocols whose usage and threat model fit SCRAM are
176      IMAP [IMAP4] and POP3 [POP3].  SCRAM provides limited protection
177      against threats to the server authentication database, but OTP
178      [OTP] may be preferable for usage scenarios where the threat to the
179      server is more serious and active attacks are not an issue.
182 3. Client Implementation of SCRAM-MD5
184      This section includes a step-by-step guide for client implementors.
185      Section 6 contains the formal definition of the syntax and is the
186      authoritative reference in case of errors here.
188      When used with SASL the mechanism name is "SCRAM-MD5".  The
189      mechanism does not provide a privacy layer, but does include an
190      optional integrity protection layer.
192      The client begins by sending a message to the server containing the
193      following three pieces of information.
195      (1) An authorization identity.  When the empty string is used, this
196      defaults to the authentication identity.  This is used by system
197      administrators or proxy servers to login with a different user
198      identity.  This field may be up to 255 octets and is terminated by
199      a NUL (0) octet.  US-ASCII printable characters are preferred,
200      although UTF-8 [UTF-8] printable characters are permitted to
201      support international names.  Use of character sets other than
202      US-ASCII and UTF-8 is forbidden.
204      (2) An authentication identity.  The identity whose passphrase will
205      be used.  This field may be up to 255 octets and is terminated by a
206      NUL (0) octet.  US-ASCII printable characters are preferred,
207      although UTF-8 [UTF-8] printable characters are permitted to
208      support international names.  Use of character sets other than
209      US-ASCII and UTF-8 is forbidden.
211      (3) A "client nonce."  It is important that this be globally
212      unique.  One common technique for generating globally unique
213      identifiers combines a process identifier with the system clock, a
214      sequence number, a random number and the client's domain name.  The
215      random number is important as clocks are often synchronized using
216      insecure protocols and are predictable.  Advice for generating good
217      random numbers can be found in [RANDOM].
219      The server responds by sending a message containing three pieces of
220      information:
225 Newman                                                          [Page 4]
227 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
230      (4) An 8-octet salt value, specific to the authentication identity.
232      (5) A one-octet bit-mask specifying security layers supported by
233      the server.  Bit 0 (value 1) indicates support for no security
234      layer and bit 1 (value 2) indicates support for an integrity
235      protection layer.  The other bits are reserved for future use (the
236      server MUST set them to zero until they are defined in a standards
237      track specification).  If the client doesn't support a security
238      layer and bit 0 is cleared, then the authentication immediately
239      fails.
241      (6) A three-octet number in network byte order (big endian),
242      containing the maximum cipher-text buffer size the server is able
243      to receive.  This may be 0 if the server supports no security
244      layers.
246      (7) A service id consisting of the service name of the protocol's
247      SASL profile followed by an "@" followed by the domain name of the
248      server and terminated by NUL.  The client SHOULD verify this is
249      correct.
251      (8) A "server nonce".  As the domain name is included in (7), this
252      only has to be unique to the server.
254      The client then does the following:
256      (A) Create a buffer containing the user's passphrase.  The client
257      MUST support passphrases of at least 64 octets.  US-ASCII
258      characters are preferred, although UTF-8 characters are permitted.
259      Character sets other than US-ASCII and UTF-8 MUST NOT be used.
261      (B) Apply the HMAC-MD5 function with (A) as the key and the 8-octet
262      salt as the data, producing a 16-octet result.  Once this is done,
263      (A) SHOULD be erased from memory.
265      (C) Apply the MD5 function to the result of (B).  This produces a
266      16-octet result.
268      (D) Apply the MD5 function to the result of (C).  This produces a
269      16-octet result.
271      (E) Create a buffer containing the server's response (4)-(8),
272      immediately followed by the initial client message (1)-(3) and the
273      client's security layer selection (9)-(10) below.
275      (F) Apply the HMAC-MD5 function with the result of (D) as the key
276      and the buffer from (E) as the data.  This produces a 16-octet
277      result.
281 Newman                                                          [Page 5]
283 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
286      (G) Create a 16-octet buffer containing the exclusive-or of (C) and
287      (F).
289      The client then sends a message to the server containing the
290      following:
292      (9) A bit-mask indicating the client selected security layer from
293      step (5).  This has a value of 01 for no security layer and 02 for
294      an integrity protection layer.
296      (10) A three octet number indicating the maximum cipher-text buffer
297      size the client is able to receive in network byte order.  If the
298      client doesn't select a security layer, this may be all zeros.
300      (11) The 16-octet result of step (G).
302      The server will respond with:
304      (12) A 16-octet server authentication verifier.
306      The client SHOULD verify this with the following procedure:
308      (H) Apply the HMAC-MD5 function with the result of (B) as the key
309      and the 8-octet salt as the data.  This produces a 16-octet result.
311      (I) Create a buffer containing the initial client message (1)-(3)
312      immediately followed by the initial server response (4)-(8) and the
313      client's security layer selection (9)-(10).
315      (J) Apply the HMAC-MD5 function with the result of (H) as the key
316      and the buffer from (I) as the data.
318      (K) If the result of (J) matches (12), the server is authenticated.
320      A secured client MAY store the result of (B) to re-authenticate to
321      services using the same salt, or the intermediate HMAC state from
322      (B) to re-authenticate to any service.  Clients SHOULD NOT store
323      the passphrase itself.
325      If integrity protection is negotiated on, the following procedure
326      is applied to each SASL security layer packet sent by the client:
328      (L) Apply the HMAC-MD5 function with the output of step (C) as the
329      key and the buffer from step (E) as the value.
331      (M) A buffer is created containing a four octet client packet
332      number in network byte order followed by the 16-octet output of
333      step (L).  The first packet sent under the SASL security layer is
337 Newman                                                          [Page 6]
339 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
342      given number 1.
344      (N) Apply the HMAC-MD5 function with (M) as the key and the
345      contents of the packet as the data.  The result is appended to the
346      end of the packet.
348      The integrity protection on packets from the server is verified as
349      follows:
351      (O) A buffer is created containing a four octet server packet
352      number in network byte order followed by the 16-octet output of
353      step (L) above.  This first packet sent under the SASL security
354      layer is given number 1.
356      (P) Apply the HMAC-MD5 function with (O) as the key and all but the
357      last 16 octets of the packet as the value.
359      (Q) Compare the last 16 octets of the packet to the output of (P).
360      If they do not match, an integrity error is produced.
363 4. Server Implementation of SCRAM-MD5
365      The section includes a step-by-step guide for server implementors
366      building on the previous section.  Section 6 contains the formal
367      definition of the syntax and is the authoritative reference in case
368      of errors here.
370      The server's authentication database contains an 8-octet salt,
371      16-octet client verifier and a 16-octet server key for each local
372      user.  The server MUST support "user@host" syntax for the
373      authentication identity at least to the extent of stripping "@host"
374      when it matches the local host name or rejecting the authentication
375      if the host name doesn't match.  The server MAY support remote user
376      authentication using this syntax.
378      The stored client verifier is equal to the result of step (D)
379      above, and the stored server key is equal to the result of step (H)
380      above.  To create its initial response, the server simply looks up
381      the authentication identity to fetch the salt, and generates an 8
382      to 248 octet nonce. This nonce MUST be unique for the server to
383      prevent replay attacks.  It can be generated by appending a system
384      clock to a process and/or thread identifier and a random number
385      [RANDOM].  To verify the client's credentials, the server performs
386      the following steps:
388      (a) Generate a buffer identical to step (E) above.
393 Newman                                                          [Page 7]
395 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
398      (b) Apply the HMAC-MD5 function with the stored client verifier as
399      the key and the result of (a) as the data.  This produces a
400      16-octet result equal to step (F) above.
402      (c) Exclusive-or the result of (b) with message (11) from the
403      client.  This produces a 16-octet result which should be equal to
404      the result of step (C) above.
406      (d) Apply the MD5 function to the output of step (c).  This
407      produces a 16-octet result which should be equal to the result of
408      step (D) above.
410      (e) if the result of (d) is equal to the stored verifier, then the
411      user is authenticated.
413      If no client challenge was provided in step (3), the server is now
414      done and responds with the appropriate status code.  Otherwise the
415      server continues as follows:
417      (f) Generate a buffer identical to step (I) above.
419      (g) Apply the HMAC-MD5 function with the stored server verifier as
420      the key and the buffer from (f) as the data.  This produces a
421      16-octet result.
423      The result of (g) is sent to the client to authenticate the server.
425      If integrity protection is negotiated on, the integrity key is
426      computed as follows:
428      (h) Apply the HMAC-MD5 function with the output of step (c) as the
429      key and the buffer from step (a) as the data.
431      Integrity generation and verification works in the same fashion as
432      the client.
435 5. Example
437      In these examples, "C:" represents lines sent from the client to
438      the server and "S:" represents lines sent from the server to the
439      client.  The wrapped lines are for editorial clarity -- there are
440      no actual newlines in the middle of the messages.
442      The following is an example of the SCRAM-MD5 mechanism using the
443      IMAP [IMAP4] profile of SASL.  For this example, the user "chris",
444      with an empty authorization identity is using the passphrase
445      "secret stuff".  The client nonce is
449 Newman                                                          [Page 8]
451 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
454      "<t4n4Pab9HB0Am/QLXB72eg@eleanor.innosoft.com>" and the server
455      nonce is "jhcNZlRuPbziFp+vLV+NCw".  No security layer is supported,
456      the salt is "testsalt" and the service identity is
457      "imap@eleanor.innosoft.com".  The complete 40 octet verifier stored
458      on the server, in hexadecimal is "74657374 73616c74 16484d56
459      7ee02f47 ac5f8a5a d5795570 90d55334 d2002df6 24cb8c8b 75708f4e."
461        C: a001 AUTHENTICATE SCRAM-MD5
462        S: +
463        C: AGNocmlzADx0NG40UGFiOUhCMEFtL1FMWEI3MmVnQGVsZWFub3IuaW
464           5ub3NvZnQuY29tPg==
465        S: + dGVzdHNhbHQBAAAAaW1hcEBlbGVhbm9yLmlubm9zb2Z0LmNvbQBq
466           aGNOWmxSdVBiemlGcCt2TFYrTkN3
467        C: AQAAAMg9jU8CeB4KOfk7sUhSQPs=
468        S: + U0odqYw3B7XIIW0oSz65OQ==
469        C:
470        S: a001 OK AUTHENTICATE completed
472      Note that base64 encoding and the lack of an initial client
473      response with the first command are characteristics of the IMAP
474      profile of SASL and not characteristics of SASL or SCRAM-MD5.  Here
475      is another example using the ACAP [ACAP] profile of SASL.  This
476      uses the same salt, passphrase and verifier as the previous
477      example.  In this example, binary data is represented as
478      hexadecimal digits enclosed in square brackets:
480        C: a001 AUTHENTICATE "SCRAM-MD5" {52}
481        C: [00]chris[00]<HSMDKNj0yFGa8f5swzqznw@eleanor.innosoft.com>
482        S: + {60}
483        S: testsalt[01000000]acap@eleanor.innosoft.com[00]
484           m6HdEYWZA5W8keNbiY40aA
485        C: {20}
486        C: [01000000 19b66406 4ce8138a e0af7b0b f0ed20ea]
487        S: a001 OK (SASL {16}
488        S: [44d7c1c4 0630fea6 5c49cb40 717a2ba5]) "Successful"
490      Note that arbitrary binary values may be used for the salt and
491      nonces, as long as the client nonce is globally unique.
494 6. Formal Syntax of SCRAM-MD5 Messages
496      This is the formal syntactic definition of the client and server
497      messages.  This uses ABNF [ABNF] notation including the core rules.
499      client-msg-1     = [authorize-id] NUL authenticate-id NUL nonce
501      server-msg-1     = salt security-info service-id NUL nonce
505 Newman                                                          [Page 9]
507 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
510      client-msg-2     = security-info client-proof
512      server-msg-2     = server-proof
514      passphrase       = *UTF8-SAFE
515                         ;; At least 64 octets MUST be supported
517      authorize-id     = *UTF8-PRINT
518                         ;; No more than 255 octets
520      authenticate-id  = *UTF8-PRINT
521                         ;; No more than 255 octets
523      security-info    = secbits bufsize
525      bufsize          = 3OCTET
526                         ;; in network byte order (big-endian)
528      secbits          = OCTET
529                         ;; bit 0 = no protection, bit 1 = integrity,
530                         ;; other bits set to 0 and reserved
532      service-id       = service-name "@" server-domain
534      service-name     = *VCHAR
535                         ;; a SASL/GSSAPI service name
537      server-domain    = *VCHAR
538                         ;; an internet domain name
540      nonce            = 8*OCTET
542      salt             = 8OCTET
544      client-proof     = 16OCTET
546      server-proof     = 16OCTET
548      NUL              = %x00  ;; US-ASCII NUL character
550      UTF8-SAFE        = %x01-09 / %x0B-0C / %x0E-7F / UTF8-MULTI
551                         ;; Any character except CR, LF, NUL
553      UTF8-PRINT       = %x20-7E / UTF8-MULTI
554                        ;; Any character except CTLs
556      UTF8-MULTI       = UTF8-2 / UTF8-3 / UTF8-4 / UTF8-5 / UTF8-6
557                         ;; UTF-8 Multi-octet characters
561 Newman                                                         [Page 10]
563 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
566      UTF8-1          = %x80-BF
568      UTF8-2          = %xC0-DF UTF8-1
570      UTF8-3          = %xE0-EF 2UTF8-1
572      UTF8-4          = %xF0-F7 3UTF8-1
574      UTF8-5          = %xF8-FB 4UTF8-1
576      UTF8-6          = %xFC-FD 5UTF8-1
579 7. System Administrator Advice
581      This section includes advice for system administrators using this
582      mechanism.
584      A SCRAM server stores three pieces of information for each user: a
585      salt, a client verifier and server key.  The latter two are derived
586      from the salt and the user's passphrase.
588      The salt prevents global dictionary attacks, similar to the salt
589      used in Unix /etc/passwd files.  As the 12 bits of salt in Unix
590      /etc/passwd has proved to be insufficient, SCRAM uses 64 bits of
591      salt.  See [SCHNEIER] for a good discussion of salt and dictionary
592      attacks.  In a multi-server site, security can be increased by
593      using a different salt on each server.
595      Although the verifiers used by SCRAM-MD5 have roughly comparable
596      security to those used by current plain-text mechanisms (such as
597      Unix /etc/passwd), it is still very important to keep them secret.
598      Just as tools exist to try common passwords against Unix
599      /etc/passwd files, it is also possible to build such tools for
600      SCRAM-MD5.  In addition, once a SCRAM-MD5 verifier is stolen, a
601      passive (undetectable) eavesdropper of that user logging in gains
602      the output of step (C) above, which is sufficient to impersonate
603      the user to all services with the same salt.  This is better than
604      current plain-text mechanisms where a passive eavesdropper always
605      recovers the user's password, but is still a serious concern.
607      Verifiers SHOULD be kept hidden from all users on the server.
608      Sites which distribute verifiers among multiple servers, SHOULD
609      encrypt them when transferring them over the network.
611      SCRAM-MD5 is only a good mechanism if passphrases are well chosen.
612      For this reason, implementations should use the term "passphrase"
613      rather than "password" and when a user's passphrase is set, site
617 Newman                                                         [Page 11]
619 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
622      policy restrictions should be applied.  A reasonably secure site
623      policy would require passphrases of at least 10 characters with at
624      least one non-alphanumeric character.
626      SCRAM-MD5 doesn't protect the privacy of data exchanged after
627      authentication.  Use of TLS [TLS], IP security ESP [IPESP] or a
628      stronger SASL mechanism such as Kerberos is encouraged if this
629      functionality is needed.
632 8. SCRAM Functional Notation
634      This section is designed to provide a quick understanding of SCRAM
635      for those who like functional notation.
637      +         octet concatenation
638      XOR       the exclusive-or function
639      AU        is the authentication user identity (NUL terminated)
640      AZ        is the authorization user identity (NUL terminated)
641                if AZ is the same as AU, a single NUL is used instead.
642      csecinfo  client security layer option bits and buffer size
643      ssecinfo  server security layer option bits and buffer size
644      service   is the name of the service and server (NUL terminated)
645      pass      is the plain-text passphrase
646      H(x)      is a one-way hash function applied to "x", such as MD5
647      MAC(x,y)  is a message authentication code (MAC) such as HMAC-MD5
648                "y" is the key and "x" is the text signed by the key.
649      salt      is a per-user salt value the server stores
650      Us        is a unique nonce the server sends to the client
651      Uc        is a unique nonce the client sends to the server
653      The SCRAM computations and exchange are as follows:
655      client-msg-1     = AZ + AU + Uc
656      (1) client -> server: client-msg-1
657      server-msg-1     = salt + ssecinfo + service + Us
658      (2) server -> client: server-msg-1
659      salted-pass      = MAC(salt, pass)
660      client-key       = H(salted-pass)
661      client-verifier  = H(client-key)
662      shared-key       = MAC(server-msg-1 + client-msg-1 + csecinfo,
663                             client-verifier)
664      client-proof     = client-key XOR shared-key
665      (3) client -> server: csecinfo + client-proof
666      server-key       = MAC(salt, salted-pass)
667      server-proof     = MAC(client-msg-1 + server-msg-1 + csecinfo,
668                             server-key)
669      (4) server -> client: server-proof
673 Newman                                                         [Page 12]
675 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
678      integrity-key    = MAC(server-msg-1 + client-msg-1 + csecinfo,
679                             client-key)
681      The server stores the salt, client-verifier and server-key.  It
682      authenticates the client by computing:
684        H(client-proof XOR shared-key)
686      after step 3 and comparing it to the stored client-verifier.  The
687      server computes the integrity-key with:
689        MAC(server-msg-1 + client-msg-1, client-proof XOR shared-key)
691      The client verifies the server by computing the server-proof
692      directly and comparing.
695 9. Security Considerations
697      Security considerations are discussed throughout this document.
698      The security considerations of MD5 [MD5] and HMAC [HMAC] also
699      apply.  SCRAM relies primarily on the one-way characteristic of MD5
700      and HMAC-MD5 for security.  The weaknesses found in MD5 are not
701      believed to impact this use.  In the interest of avoiding
702      proliferation of authentication mechanisms, it is hoped that it
703      will be easy to deploy public-key technology before a hash function
704      upgrade becomes necessary.
706      SCRAM does use the output of an HMAC function and exclusive-or to
707      construct a simple 16-octet encryption function.  While
708      constructing an encryption function from a hash function is
709      normally a questionable practice [SCHNEIER], in this case both the
710      key and the data are outputs of a one-way hash function with a good
711      bit-distribution and the key is used only once (as long as the
712      combined nonces are unique).
714      An analysis of different attacks follows:
716      Passive Network Attacks
718      SCRAM is resistant to replay attacks as long as the appropriate
719      nonce is unique.
721      SCRAM is not resistant to passive dictionary attacks.  User
722      education, passphrase setting policy and external confidentiality
723      services can be used to protect against such attacks.
725      SCRAM does not protect against session data eavesdropping.  An
729 Newman                                                         [Page 13]
731 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
734      external confidentiality service is necessary to protect against
735      eavesdropping.  TLS [TLS] and IP security ESP [IPESP] are examples
736      of IETF standards-track mechanisms to provide confidentiality.
738      Active Network Attacks
740      If the client fails to verify the server proof, then SCRAM provides
741      no protection from active attacks.
743      SCRAM protects against server impersonation with the server mutual
744      authentication.
746      An attacker could use SCRAM to probe for users by trying each user
747      name twice to see if the salt varies.  The server can prevent this
748      attack by inventing consistent salt values for non-users.  One way
749      to do this would be to store a random secret and generate the salt
750      using HMAC(user-name, random-secret).
752      SASL is susceptible to downgrade active attacks which reduce the
753      advertised authentication mechanisms to the weakest the server
754      offers.  If SCRAM is the weakest mechanism, such attacks can be
755      detected if integrity protection is negotiated on and the client
756      requests a duplicate copy of the server's capability list after
757      authentication (e.g., by re-issuing the CAPABILITY command in
758      IMAP).  For a protocol such as ACAP [ACAP], the server SHOULD
759      repeat the greeting line immediately after authentication is
760      completed whenever integrity protection is negotiated on.
762      SCRAM can detect insertion, deletion and modification of session
763      data only if integrity protection is negotiated on.  TLS [TLS] or
764      IP security services [IPAUTH, IPESP] may also be used to protect
765      against such tampering.  If TLS or IP security integrity protection
766      is active, then the SCRAM integrity layer is unnecessary and SHOULD
767      be negotiated off.
769      Upper level security services, such as SCRAM and TLS, can not
770      protect against denial of service attacks on the TCP/IP layer.  In
771      addition, if no integrity layer is used, then SCRAM is vulnerable
772      to TCP session stealing attacks [CERT-IPSPOOF].  IP security
773      services [IPAUTH, IPESP] can protect against many of these attacks.
775      SCRAM is not susceptible to the race and denial of service attacks
776      mentioned in section 9 of the OTP specification [OTP].
778      Server Attacks
780      A server implementation which does not tolerate input of any length
781      with any content may be susceptible to attacks which permit
785 Newman                                                         [Page 14]
787 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
790      privileged access to the server.  For this reason server
791      implementations MUST be able to accept input of any length with any
792      content although server implementations MAY refuse to authenticate
793      the client if messages exceed the specified maximum lengths.  Note
794      that the ANSI C gets() library function does not meet this
795      requirement.
797      An attacker which has access to both the SCRAM verifier and a
798      client exchange for a particular user gains the ability to
799      impersonate that user to other servers using the same salt.  An
800      external confidentiality service can make it more difficult to
801      obtain the client exchange, but can not defend against installation
802      of a trojan horse on a compromised server.
804      In the process of authentication, the server gains access to the
805      client-key which is sufficient to impersonate the user to other
806      services with the same salt.
808      The limited service trust feature (step 7 above) includes the
809      service name and the server host name.  A server host which is
810      authorized to provide one service can impersonate that service at
811      other hosts in the same realm by an active attack on the DNS system
812      when used by the client.  Use of secure DNS [DNSSEC] on the client
813      limits this vulnerability.
815      Client Attacks
817      As SCRAM is designed for user entry of a plain-text passphrase, it
818      is vulnerable to passphrase hijacking by trojan horse clients.  OTP
819      [OTP] with an external portable OTP calculator can limit the
820      vulnerability to a single session.
823 10. Intellectual Property Issues and Prior Art
825      The author is not aware of any patents or pending patents which
826      apply to this mechanism.
828      This is primarily a derivative of simple hash-based challenge
829      response systems.  The hash-based challenge response idea has
830      existed since at least 1992, when the RIPE project published the
831      SKID algorithm according to [SCHNEIER].
833      The repeated-hash idea used to verify the client's authenticator is
834      derived from S/KEY [SKEY].
836      The idea of using salt to protect against global dictionary attacks
837      dates back to at least the Unix /etc/passwd system.  There is some
841 Newman                                                         [Page 15]
843 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
846      discussion of this in [SCHNEIER].
848      SCRAM combines these techniques.  The author of this specification
849      first proposed this idea on a public mailing list on July 16, 1997.
852 11. Multinational Considerations
854      As remote access is a crucial service, users are encouraged to
855      restrict user names and passphrases to the US-ASCII character set.
856      However, if characters outside the US-ASCII character set are used
857      in user names and passphrases, then they are interpreted according
858      to UTF-8 [UTF-8] and it is a protocol error to include any octet
859      sequences not legal for UTF-8.  Servers are encouraged to enforce
860      this restriction to discourage clients which use unlabeled
861      character sets in this context.
864 12. References
866      [ABNF] Crocker, Overell, "Augmented BNF for Syntax Specifications:
867      ABNF", RFC 2234, Internet Mail Consortium, Demon Internet Ltd,
868      November 1997.
870      [ACAP] Newman, Myers, "ACAP -- Application Configuration Access
871      Protocol", RFC 2244, Innosoft, Netscape, November 1997.
873      [CERT-IPSPOOF] CERT, "TCP SYN Flooding and IP Spoofing Attacks",
874      CERT CA-96.21, CERT, September 1996.
876      [CRAM-MD5] Klensin, Catoe, Krumviede, "IMAP/POP AUTHorize Extension
877      for Simple Challenge/Response", RFC 2195, MCI, September 1997.
879      [DNSSEC] Eastlake, Kaufman, "Domain Name System Security
880      Extensions", RFC 2065, CyberCash, Iris, January 1997.
882      [HMAC] Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for Message
883      Authentication", RFC 2104, IBM, UCSD, February 1997.
885      [IMAP4] Crispin, M., "Internet Message Access Protocol - Version
886      4rev1", RFC 2060, University of Washington, December 1996.
888      [IPAUTH] Atkinson, "IP Authentication Header", RFC 1826, Naval
889      Research Laboratory, August 1995.
891      [IPESP] Atkinson, "IP Encapsulating Security Payload (ESP)", RFC
892      1827, Naval Research Laboratory, August 1995.
897 Newman                                                         [Page 16]
899 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
902      [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate
903      Requirement Levels", RFC 2119, Harvard University, March 1997.
905      [MD5] Rivest, "The MD5 Message Digest Algorithm", RFC 1321, MIT
906      Laboratory for Computer Science, April 1992.
908      [OTP] Haller, Metz, "A One-Time Password System", RFC 1938,
909      Bellcore, Kaman Sciences Corporation, May 1996.
911      [OTP-EXT] Metz, "OTP Extended Responses", RFC 2243, The Inner Net,
912      November 1997.
914      [POP3] Myers, J., Rose, M., "Post Office Protocol - Version 3", RFC
915      1939, Carnegie Mellon, Dover Beach Consulting, Inc., May 1996.
917      [RANDOM] Eastlake, Crocker, Schiller, "Randomness Recommendations
918      for Security", RFC 1750, DEC, Cybercash, MIT, December 1994.
920      [SASL] Myers, "Simple Authentication and Security Layer (SASL)",
921      RFC 2222, Netscape Communications, October 1997.
923      [SCHNEIER] Schneier, "Applied Cryptography: Protocols, Algorithms
924      and Source Code in C," John Wiley and Sons, Inc., 1996.
926      [SKEY] Haller, Neil M. "The S/Key One-Time Password System", RFC
927      1760, Bellcore, February 1995.
929      [TLS] Dierks, Allen, "The TLS Protocol Version 1.0", Work in
930      progress.
932      [UTF8] Yergeau, F. "UTF-8, a transformation format of ISO 10646",
933      RFC 2279, Alis Technologies, January 1998.
936 13. Author's Address
938      Chris Newman
939      Innosoft International, Inc.
940      1050 Lakes Drive
941      West Covina, CA 91790 USA
943      Email: chris.newman@innosoft.com
946 A. Appendix - Additional Services
948      Several additional services are needed to make SCRAM useful in more
949      usage scenarios.  These include remote authentication database
953 Newman                                                         [Page 17]
955 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
958      support for servers, authentication database APIs for servers,
959      remote passphrase change support for clients, single-sign-on APIs
960      for clients and management tools.  The service-id and server-key
961      are included to facilitate the remote authentication database
962      service.  Otherwise these issues are deferred for future work.
964 B. Appendix - HMAC-MD5 Sample Source Code
966      The following sample C source code calls the source code in the MD5
967      specification [MD5] and is derived from the source code in [HMAC].
968      It is needed by the SCRAM source code in the next section.
970      The client may call hmac_md5_precalc() to save the intermediate
971      HMAC result for later use in hmac_md5_import().  This can be used
972      by a CRAM-MD5 [CRAM-MD5] or a SCRAM-MD5 [SCRAM-MD5] client to save
973      an intermediate result suitable for use with any server without
974      saving the plain-text passphrase.
976      /* hmac-md5.h -- HMAC_MD5 functions
977       */
978      #define HMAC_MD5_SIZE 16
980      /* intermediate MD5 context */
981      typedef struct HMAC_MD5_CTX_s {
982          MD5_CTX ictx, octx;
983      } HMAC_MD5_CTX;
985      /* intermediate HMAC state
986       *  values stored in network byte order (Big Endian)
987       */
988      typedef struct HMAC_MD5_STATE_s {
989          UINT4 istate[4];
990          UINT4 ostate[4];
991      } HMAC_MD5_STATE;
993      /* One step hmac computation
994       *
995       * digest may be same as text or key
996       */
997      void hmac_md5(const unsigned char *text, int text_len,
998                 const unsigned char *key, int key_len,
999                 unsigned char digest[HMAC_MD5_SIZE]);
1001      /* create context from key
1002       */
1003      void hmac_md5_init(HMAC_MD5_CTX *hmac,
1004              const unsigned char *key, int key_len);
1009 Newman                                                         [Page 18]
1011 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1014      /* precalculate intermediate state from key
1015       */
1016      void hmac_md5_precalc(HMAC_MD5_STATE *hmac,
1017                 const unsigned char *key, int key_len);
1019      /* initialize context from intermediate state
1020       */
1021      void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state);
1023      #define hmac_md5_update(hmac, text, text_len) \
1024        MD5Update(&(hmac)->ictx, (text), (text_len))
1026      /* finish hmac from intermediate result.
1027       *  Intermediate result is erased.
1028       */
1029      void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
1030               HMAC_MD5_CTX *hmac);
1033      /* hmac-md5.c -- HMAC MD5 Keyed-Hashing by Chris Newman
1034       *  derived from RFC 2104 by H. Krawczyk, M. Bellare, R.Canetti
1035       */
1036      #include <stdio.h>
1037      #include <string.h>
1038      #include "md5.h"
1039      #include "hmac-md5.h"
1041      /* for htonl() and ntohl() */
1042      #include <sys/types.h>
1043      #include <netinet/in.h>
1045      /* MD5 block size */
1046      #define BLOCK_SIZE 64
1048      void hmac_md5_init(HMAC_MD5_CTX *hmac,
1049              const unsigned char *key, int key_len)
1050      {
1051          unsigned char k_pad[BLOCK_SIZE];    /* padded key */
1052          int i;
1054          /* if key longer than BLOCK_SIZE bytes reset to MD5(key) */
1055          if (key_len > BLOCK_SIZE) {
1056           MD5Init(&hmac->ictx);
1057           MD5Update(&hmac->ictx, key, key_len);
1058           MD5Final(k_pad, &hmac->ictx);
1059           key = k_pad;
1060           key_len = HMAC_MD5_SIZE;
1061          }
1065 Newman                                                         [Page 19]
1067 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1071          /* XOR padded key with inner pad value */
1072          for (i = 0; i < key_len; i++) {
1073           k_pad[i] = key[i] ^ 0x36;
1074          }
1075          while (i < BLOCK_SIZE) {
1076           k_pad[i++] = 0x36;
1077          }
1079          /* Begin inner MD5 */
1080          MD5Init(&hmac->ictx);
1081          MD5Update(&hmac->ictx, k_pad, BLOCK_SIZE);
1083          /* XOR padded key with outer pad value */
1084          for (i = 0; i < BLOCK_SIZE; ++i) {
1085           k_pad[i] ^= (0x36 ^ 0x5c);
1086          }
1088          /* Begin outer MD5 */
1089          MD5Init(&hmac->octx);
1090          MD5Update(&hmac->octx, k_pad, BLOCK_SIZE);
1092          /* clean up workspace */
1093          memset(k_pad, 0, BLOCK_SIZE);
1094      }
1096      void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
1097               HMAC_MD5_CTX *hmac)
1098      {
1099          /* finish inner MD5 */
1100          MD5Final(digest, &hmac->ictx);
1101          /* finish outer MD5 */
1102          MD5Update(&hmac->octx, digest, HMAC_MD5_SIZE);
1103          MD5Final(digest, &hmac->octx);
1104          /* MD5Final zeros context */
1105      }
1107      void hmac_md5(const unsigned char *text, int text_len,
1108                 const unsigned char *key, int key_len,
1109                 unsigned char digest[HMAC_MD5_SIZE])
1110      {
1111          HMAC_MD5_CTX hmac;
1113          hmac_md5_init(&hmac, key, key_len);
1114          hmac_md5_update(&hmac, text, text_len);
1115          hmac_md5_final(digest, &hmac);
1116      }
1121 Newman                                                         [Page 20]
1123 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1126      void hmac_md5_precalc(HMAC_MD5_STATE *ctx,
1127           const unsigned char *pass, int passlen)
1128      {
1129          HMAC_MD5_CTX hctx;
1131          if (passlen == 0) passlen = strlen((const char *) pass);
1132          hmac_md5_init(&hctx, pass, passlen);
1133          ctx->istate[0] = htonl(hctx.ictx.state[0]);
1134          ctx->istate[1] = htonl(hctx.ictx.state[1]);
1135          ctx->istate[2] = htonl(hctx.ictx.state[2]);
1136          ctx->istate[3] = htonl(hctx.ictx.state[3]);
1137          ctx->ostate[0] = htonl(hctx.octx.state[0]);
1138          ctx->ostate[1] = htonl(hctx.octx.state[1]);
1139          ctx->ostate[2] = htonl(hctx.octx.state[2]);
1140          ctx->ostate[3] = htonl(hctx.octx.state[3]);
1141          memset(&hctx, 0, sizeof (hctx));
1142      }
1145      void hmac_md5_import(HMAC_MD5_CTX *hctx, HMAC_MD5_STATE *ctx)
1146      {
1147          hctx->ictx.state[0] = ntohl(ctx->istate[0]);
1148          hctx->ictx.state[1] = ntohl(ctx->istate[1]);
1149          hctx->ictx.state[2] = ntohl(ctx->istate[2]);
1150          hctx->ictx.state[3] = ntohl(ctx->istate[3]);
1151          hctx->octx.state[0] = ntohl(ctx->ostate[0]);
1152          hctx->octx.state[1] = ntohl(ctx->ostate[1]);
1153          hctx->octx.state[2] = ntohl(ctx->ostate[2]);
1154          hctx->octx.state[3] = ntohl(ctx->ostate[3]);
1155          hctx->ictx.count[0] = hctx->octx.count[0] = BLOCK_SIZE << 3;
1156          hctx->ictx.count[1] = hctx->octx.count[1] = 0;
1157      }
1177 Newman                                                         [Page 21]
1179 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1182 C. Appendix - SCRAM sample source code
1184      The following sample source code implements SCRAM itself for both
1185      server and client.
1187      Please note the lines marked "XXX: ..." as they need to be
1188      translated from English to computer readable code.
1190      A client implementation simply calls scram_md5_generate() with the
1191      passphrase after receiving the first server reply.  The cproof
1192      parameter will hold the message to send to the server and the
1193      sproof parameter will hold the expected server mutual
1194      authentication.  The clidata parameter holds the client's security
1195      layer selections.  A client may also call hmac_md5_precalc() to
1196      turn a passphrase into CRAM/SCRAM credentials for later use in
1197      scram_md5_generate().
1199      A server implementation simply calls scram_md5_generate() with the
1200      stored verifier, the second client message and the SCRAM_VERIFY
1201      option.  Server verifiers are generated by creating a random salt
1202      and calling scram_md5_vgen() with either the passphrase or
1203      CRAM/SCRAM credentials.
1205      If integrity protection is desired, the integrity_key parameter may
1206      be provided to scram_md5_generate() and will receive the resulting
1207      key.  Generating an verifying the integrity protection is left as
1208      an exercise to the reader.
1210      /* scram.h -- scram utility functions
1211       */
1212      /* size of SCRAM_MD5 salt and verifier */
1213      #define SCRAM_MD5_SALTSIZE 8
1214      #define SCRAM_MD5_DATASIZE 16
1216      /* SCRAM verifier */
1217      typedef struct SCRAM_MD5_VRFY_s {
1218          unsigned char salt[SCRAM_MD5_SALTSIZE];
1219          unsigned char clidata[SCRAM_MD5_DATASIZE];
1220          unsigned char svrdata[SCRAM_MD5_DATASIZE];
1221      } SCRAM_MD5_VRFY;
1223      /* Client proof message */
1224      typedef struct SCRAM_MD5_CLIENT_s {
1225          unsigned char secprops[4];
1226          unsigned char cproof[SCRAM_MD5_DATASIZE];
1227      } SCRAM_MD5_CLIENT;
1229      /* generate SCRAM-MD5 verifier
1233 Newman                                                         [Page 22]
1235 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1238       *  vptr      -- gets result
1239       *  salt      -- contains salt of SCRAM_MD5_SALTSIZE
1240       *  pass      -- passphrase or verifier
1241       *  passlen   -- len of pass/verifier (0 ok if NUL terminated)
1242       *  plainflag -- 1 = plaintext passphrase,
1243       *               0 = result of hmac_md5_precalc()
1244       *  clientkey -- cache for client proof, usually NULL
1245       */
1246      void scram_md5_vgen(SCRAM_MD5_VRFY *vptr,
1247                          const unsigned char *salt,
1248                          const char *pass, int passlen, int plainflag,
1249                          unsigned char *clientkey);
1251      /* scram secret action type */
1252      #define SCRAM_CREDENTIAL 0 /* generate replies using credentials */
1253      #define SCRAM_PLAINTEXT  1 /* generate replies using plaintext */
1254      #define SCRAM_VERIFY     2 /* use SCRAM_MD5_VRFY to verify client,
1255                                    and generate server reply */
1257      /* generate or verify SCRAM-MD5
1258       * input params:
1259       *  cchal         -- client challenge string
1260       *  cchallen      -- length of client challenge
1261       *  schal         -- server challenge string
1262       *  schallen      -- length of server challenge
1263       *  secret        -- passphrase, credentials, or verifier
1264       *  secretlen     -- length of passphrase (0 ok if NUL terminated)
1265       *  action        -- see above
1266       * in/out:
1267       *  clidata       -- client data for client response
1268       * output:
1269       *  sproof        -- server proof of length SCRAM_MD5_DATASIZE
1270       *  integrity_key -- integrity key of length SCRAM_MD5_DATASIZE
1271       *                   caller may pass NULL if no integrity needed
1272       * returns:
1273       *  -2 if params invalid
1274       *  -1 if verify fails
1275       *   0 on success
1276       */
1277      int scram_md5_generate(const char *cchal, int cchallen,
1278                             const char *schal, int schallen,
1279                             const char *secret, int secretlen,
1280                             int action,
1281                             SCRAM_MD5_CLIENT *clidata,
1282                             unsigned char *sproof,
1283                             unsigned char *integrity_key);
1289 Newman                                                         [Page 23]
1291 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1294      /* scram.c -- routines for SCRAM-MD5 calculations
1295       */
1296      #include <stdio.h>
1297      #include <stdlib.h>
1298      #include <string.h>
1299      #include "md5.h"
1300      #include "hmac-md5.h"
1301      #include "scram.h"
1303      void scram_md5_vgen(SCRAM_MD5_VRFY *vptr,
1304                          const unsigned char *salt,
1305                          const char *pass, int passlen, int plainflag,
1306                          unsigned char *clientkey)
1307      {
1308          HMAC_MD5_CTX hctx;
1310          if (clientkey == NULL) clientkey = vptr->clidata;
1312          /* get context */
1313          if (plainflag) {
1314              if (passlen == 0) passlen = strlen(pass);
1315              hmac_md5_init(&hctx, (const unsigned char *) pass,
1316                            passlen);
1317          } else {
1318              hmac_md5_import(&hctx, (HMAC_MD5_STATE *) pass);
1319          }
1321          /* generate salted passphrase */
1322          hmac_md5_update(&hctx, salt, SCRAM_MD5_SALTSIZE);
1323          hmac_md5_final(vptr->clidata, &hctx);
1325          /* generate server proof */
1326          hmac_md5(salt, SCRAM_MD5_SALTSIZE, vptr->clidata,
1327                   sizeof (vptr->clidata), vptr->svrdata);
1329          /* generate client key and client verifier */
1330          MD5Init(&hctx.ictx);
1331          MD5Update(&hctx.ictx, vptr->clidata, sizeof (vptr->clidata));
1332          MD5Final(clientkey, &hctx.ictx);
1333          MD5Init(&hctx.ictx);
1334          MD5Update(&hctx.ictx, clientkey, SCRAM_MD5_DATASIZE);
1335          MD5Final(vptr->clidata, &hctx.ictx);
1337          /* copy salt to verifier */
1338          if (salt != vptr->salt) {
1339              memcpy(vptr->salt, salt, SCRAM_MD5_SALTSIZE);
1340          }
1341      }
1345 Newman                                                         [Page 24]
1347 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1350      int scram_md5_generate(const char *cchal, int cchallen,
1351                             const char *schal, int schallen,
1352                             const char *secret, int secretlen,
1353                             int action,
1354                             SCRAM_MD5_CLIENT *clidata,
1355                             unsigned char *sproof,
1356                             unsigned char *integrity_key)
1357      {
1358          SCRAM_MD5_VRFY verifier, *vptr;
1359          HMAC_MD5_CTX hctx;
1360          unsigned char clientkey[HMAC_MD5_SIZE];
1361          unsigned char sharedkey[HMAC_MD5_SIZE];
1362          int i, result = 0;
1364          /* check params */
1365          if ((action == SCRAM_CREDENTIAL
1366            && secretlen != sizeof (HMAC_MD5_STATE))
1367              || (action == SCRAM_VERIFY
1368                  && secretlen != sizeof (verifier))
1369              || schallen < SCRAM_MD5_SALTSIZE) {
1370              return (-2);
1371          }
1373          /* get verifier */
1374          if (action == SCRAM_VERIFY) {
1375              vptr = (SCRAM_MD5_VRFY *) secret;
1376          } else {
1377              scram_md5_vgen(&verifier, (const unsigned char *) schal,
1378                             secret, secretlen, action, clientkey);
1379              vptr = &verifier;
1380          }
1382          /* calculate shared key */
1383          hmac_md5_init(&hctx, vptr->clidata, sizeof (vptr->clidata));
1384          hmac_md5_update(&hctx, (unsigned char *) schal, schallen);
1385          hmac_md5_update(&hctx, (unsigned char *) cchal, cchallen);
1386          hmac_md5_update(&hctx, clidata->secprops, 4);
1387          hmac_md5_final(sharedkey, &hctx);
1389          if (action == SCRAM_VERIFY) {
1390              /* verify client proof */
1391              for (i = 0; i < HMAC_MD5_SIZE; ++i) {
1392                  XXX: the line which belongs here is omitted due to
1393                  U.S. export regulations, but it exclusive-ors the
1394                  "sharedkey" with the "clidata->cproof" and places the
1395                  result in "clientkey" (see step (c) above)
1396              }
1397              MD5Init(&hctx.ictx);
1401 Newman                                                         [Page 25]
1403 Internet Draft          SCRAM-MD5 SASL Mechanism              March 1998
1406              MD5Update(&hctx.ictx, clientkey, sizeof (clientkey));
1407              MD5Final(sharedkey, &hctx.ictx);
1408              if (memcmp(sharedkey, vptr->clidata,
1409                         sizeof (sharedkey)) != 0) {
1410                  result = -1;
1411              }
1412          } else {
1413              /* generate client proof */
1414              for (i = 0; i < HMAC_MD5_SIZE; ++i) {
1415                  XXX: the line which belongs here is omitted due to
1416                  U.S. export regulations, but it exclusive-ors the
1417                  "sharedkey" with the "clientkey" and places the
1418                  result in "clidata->cproof" (see step (G) above)
1419              }
1420          }
1422          /* calculate integrity key */
1423          if (integrity_key != NULL) {
1424              hmac_md5_init(&hctx, clientkey, HMAC_MD5_SIZE);
1425              hmac_md5_update(&hctx, (unsigned char *) schal, schallen);
1426              hmac_md5_update(&hctx, (unsigned char *) cchal, cchallen);
1427              hmac_md5_update(&hctx, clidata->secprops, 4);
1428              hmac_md5_final(integrity_key, &hctx);
1429          }
1431          /* calculate server result */
1432          if (result == 0) {
1433              hmac_md5_init(&hctx, vptr->svrdata, HMAC_MD5_SIZE);
1434              hmac_md5_update(&hctx, (unsigned char *) cchal, cchallen);
1435              hmac_md5_update(&hctx, (unsigned char *) schal, schallen);
1436              hmac_md5_update(&hctx, clidata->secprops, 4);
1437              hmac_md5_final(sproof, &hctx);
1438          }
1440          /* cleanup workspace */
1441          memset(clientkey, 0, sizeof (clientkey));
1442          memset(sharedkey, 0, sizeof (sharedkey));
1443          if (vptr == &verifier) memset(&verifier, 0, sizeof (verifier));
1445          return (result);
1446      }
1457 Newman                                                         [Page 26]