gsasl-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CVS gsasl/lib/digest-md5


From: gsasl-commit
Subject: CVS gsasl/lib/digest-md5
Date: Sun, 19 Dec 2004 18:31:52 +0100

Update of /home/cvs/gsasl/lib/digest-md5
In directory dopio:/tmp/cvs-serv2084

Modified Files:
        test-parser.c Makefile.am 
Added Files:
        digesthmac.h digesthmac.c 
Log Message:
Modularize digest computation into digesthmac.*.


--- /home/cvs/gsasl/lib/digest-md5/test-parser.c        2004/12/19 08:23:38     
1.7
+++ /home/cvs/gsasl/lib/digest-md5/test-parser.c        2004/12/19 17:31:51     
1.8
@@ -26,6 +26,7 @@
 
 #include "parser.h"
 #include "printer.h"
+#include "digesthmac.h"
 
 int
 main (int argc, char *argv[])
@@ -33,6 +34,8 @@
   digest_md5_challenge c;
   digest_md5_response r;
   digest_md5_finish f;
+  char buf32[33];
+  char buf16[16];
   int rc;
   char *tmp;
 
@@ -170,5 +173,17 @@
     printf ("invalid? PASS\n", token);
   }
 
+  memset (buf16, 'Q', 16);
+
+  rc = digest_md5_hmac (buf32, buf16, "nonce", 1, "cnonce", 
DIGEST_MD5_QOP_AUTH,
+                       "authzid", "digesturi", ":", 0,
+                       NULL, NULL, NULL, NULL);
+  if (rc != 0)
+    abort ();
+  buf32[32] = '\0';
+  if (strcmp (buf32, "6a204da26b9888ee40bb3052ff056a67") != 0)
+    abort ();
+  printf ("digest: `%s': PASS\n", buf32);
+
   return 0;
 }
--- /home/cvs/gsasl/lib/digest-md5/Makefile.am  2004/12/19 05:36:12     1.18
+++ /home/cvs/gsasl/lib/digest-md5/Makefile.am  2004/12/19 17:31:51     1.19
@@ -27,6 +27,7 @@
        session.h session.c \
        getsubopt.c \
        tokens.h \
+       digesthmac.h digesthmac.c \
        validate.h validate.c \
        parser.h parser.c \
        printer.h printer.c \
@@ -40,5 +41,5 @@
 libgsasl_digest_md5_la_SOURCES += server.c
 endif
 
-LDADD = libgsasl-digest_md5.la
+LDADD = libgsasl-digest_md5.la ../crypto/libgc.la
 check_PROGRAMS = test-parser

--- /home/cvs/gsasl/lib/digest-md5/digesthmac.h 2004/12/19 17:31:52     NONE
+++ /home/cvs/gsasl/lib/digest-md5/digesthmac.h 2004/12/19 17:31:52     1.1
/* digesthmac.h --- Compute DIGEST-MD5 response value.
 * Copyright (C) 2004  Simon Josefsson
 *
 * This file is part of GNU SASL Library.
 *
 * GNU SASL Library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * GNU SASL Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GNU SASL Library; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 *
 */

#ifndef DIGEST_MD5_DIGESTHMAC_H
# define DIGEST_MD5_DIGESTHMAC_H

/* Get token types. */
#include "tokens.h"

#define DIGEST_MD5_LENGTH 16

extern int digest_md5_hmac (char *output, char secret[DIGEST_MD5_LENGTH],
                            char *nonce, unsigned long nc, char *cnonce,
                            digest_md5_qop qop, char *authzid, char *digesturi,
                            const char *a2string, digest_md5_cipher cipher,
                            char *kic, char *kis, char *kcc, char *kcs);

#endif /* DIGEST_MD5_DIGESTHMAC_H */
--- /home/cvs/gsasl/lib/digest-md5/digesthmac.c 2004/12/19 17:31:52     NONE
+++ /home/cvs/gsasl/lib/digest-md5/digesthmac.c 2004/12/19 17:31:52     1.1
/* digesthmac.c --- Compute DIGEST-MD5 response value.
 * Copyright (C) 2002, 2003, 2004  Simon Josefsson
 *
 * This file is part of GNU SASL Library.
 *
 * GNU SASL Library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * GNU SASL Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GNU SASL Library; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 *
 */

#if HAVE_CONFIG_H
# include "config.h"
#endif

/* Get specification. */
#include "digesthmac.h"

/* Get malloc, free. */
#include <stdlib.h>

/* Get memcpy, strlen. */
#include <string.h>

/* Get sprintf. */
#include <stdio.h>

/* Get gc_md5. */
#include <gc.h>

#define HEXCHAR(c) ((c & 0x0F) > 9 ? 'a' + (c & 0x0F) - 10 : '0' + (c & 0x0F))

#define QOP_AUTH "auth"
#define QOP_AUTH_INT "auth-int"
#define QOP_AUTH_CONF "auth-conf"

#define A2_PRE "AUTHENTICATE:"
#define A2_POST ":00000000000000000000000000000000"
#define COLON ":"
#define MD5LEN 16
#define RESPONSE_LENGTH 32
#define RSPAUTH_LENGTH RESPONSE_LENGTH
#define DERIVE_CLIENT_INTEGRITY_KEY_STRING \
  "Digest session key to client-to-server signing key magic constant"
#define DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN 65
#define DERIVE_SERVER_INTEGRITY_KEY_STRING \
  "Digest session key to server-to-client signing key magic constant"
#define DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN 65
#define DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING \
  "Digest H(A1) to client-to-server sealing key magic constant"
#define DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN 59
#define DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING \
  "Digest H(A1) to server-to-client sealing key magic constant"
#define DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN 59

/* Compute in 32 bytes large array OUTPUT the DIGEST-MD5 response
   value.  SECRET holds the 16 bytes MD5 hash SS, i.e.,
   H(username:realm:passwd).  NONCE is a zero terminated string with
   the server nonce.  NC is the nonce-count, typically 1 for initial
   authentication.  CNONCE is a zero terminated string with the client
   nonce.  QOP is the quality of protection to use.  AUTHZID is a zero
   terminated string with the authorization identity.  DIGESTURI is a
   zero terminated string with the server principal (e.g.,
   imap/mail.example.org).  A2STRING is a zero terminated string that
   should either be "AUTHENTICATE:" or ":".  CIPHER is the cipher to
   use.  KIC, KIS, KCC, KCS are either NULL, or points to 16 byte
   arrays that will hold the computed keys on output.  Returns 0 on
   success. */
int
digest_md5_hmac (char *output, char secret[MD5LEN], char *nonce,
                 unsigned long nc, char *cnonce, digest_md5_qop qop,
                 char *authzid, char *digesturi, const char *a2string,
                 digest_md5_cipher cipher,
                 char *kic, char *kis, char *kcc, char *kcs)
{
  char nchex[9];
  char a1hexhash[2 * MD5LEN];
  char a2hexhash[2 * MD5LEN];
  char hash[MD5LEN];
  char *tmp, *p;
  size_t tmplen;
  int rc;
  int i;

  /* A1 */

  tmplen = MD5LEN + strlen (COLON) + strlen (nonce) +
    strlen (COLON) + strlen (cnonce);
  if (authzid && strlen (authzid) > 0)
    tmplen += strlen (COLON) + strlen (authzid);

  p = tmp = malloc (tmplen);
  if (tmp == NULL)
    return -1;

  memcpy (p, secret, MD5LEN);
  p += MD5LEN;
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, nonce, strlen (nonce));
  p += strlen (nonce);
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, cnonce, strlen (cnonce));
  p += strlen (cnonce);
  if (authzid && strlen (authzid) > 0)
    {
      memcpy (p, COLON, strlen (COLON));
      p += strlen (COLON);
      memcpy (p, authzid, strlen (authzid));
      p += strlen (authzid);
    }

  rc = gc_md5 (tmp, tmplen, hash);
  free (tmp);
  if (rc)
    return rc;

  if (kic)
    {
      char hash2[MD5LEN];
      char tmp[MD5LEN + DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN];
      size_t tmplen = MD5LEN + DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN;

      memcpy (tmp, hash, MD5LEN);
      memcpy (tmp + MD5LEN, DERIVE_CLIENT_INTEGRITY_KEY_STRING,
              DERIVE_CLIENT_INTEGRITY_KEY_STRING_LEN);

      rc = gc_md5 (tmp, tmplen, hash2);
      if (rc)
        return rc;

      memcpy (kic, hash2, MD5LEN);
    }

  if (kis)
    {
      char hash2[MD5LEN];
      char tmp[MD5LEN + DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN];

      memcpy (tmp, hash, MD5LEN);
      memcpy (tmp + MD5LEN, DERIVE_SERVER_INTEGRITY_KEY_STRING,
              DERIVE_SERVER_INTEGRITY_KEY_STRING_LEN);

      rc = gc_md5 (tmp,
                   MD5LEN + DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN,
                   hash2);
      if (rc)
        return rc;

      memcpy (kis, hash2, MD5LEN);
    }

  if (kcc)
    {
      char hash2[MD5LEN];
      int n;
      char tmp[MD5LEN + DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN];

      if (cipher == DIGEST_MD5_CIPHER_RC4_40)
        n = 5;
      else if (cipher == DIGEST_MD5_CIPHER_RC4_56)
        n = 7;
      else
        n = MD5LEN;

      memcpy (tmp, hash, n);
      memcpy (tmp + n, DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING,
              DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN);

      rc = gc_md5 (tmp, n + DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING_LEN,
                      hash2);
      if (rc)
        return rc;

      memcpy (kcc, hash2, MD5LEN);
    }

  if (kcs)
    {
      char hash2[MD5LEN];
      int n;
      char tmp[MD5LEN + DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN];

      if (cipher == DIGEST_MD5_CIPHER_RC4_40)
        n = 5;
      else if (cipher == DIGEST_MD5_CIPHER_RC4_56)
        n = 7;
      else
        n = MD5LEN;

      memcpy (tmp, hash, n);
      memcpy (tmp + n, DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING,
              DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN);

      rc = gc_md5 (tmp, n + DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING_LEN,
                      hash2);
      if (rc)
        return rc;

      memcpy (kcs, hash2, MD5LEN);
    }

  for (i = 0; i < MD5LEN; i++)
    {
      a1hexhash[2 * i + 1] = HEXCHAR (hash[i]);
      a1hexhash[2 * i + 0] = HEXCHAR (hash[i] >> 4);
    }

  /* A2 */

  tmplen = strlen (a2string) + strlen (digesturi);
  if (qop & DIGEST_MD5_QOP_AUTH_INT || qop & DIGEST_MD5_QOP_AUTH_CONF)
    tmplen += strlen (A2_POST);

  p = tmp = malloc (tmplen);
  if (tmp == NULL)
    return -1;

  memcpy (p, a2string, strlen (a2string));
  p += strlen (a2string);
  memcpy (p, digesturi, strlen (digesturi));
  p += strlen (digesturi);
  if (qop & DIGEST_MD5_QOP_AUTH_INT || qop & DIGEST_MD5_QOP_AUTH_CONF)
    memcpy (p, A2_POST, strlen (A2_POST));

  rc = gc_md5 (tmp, tmplen, hash);
  free (tmp);
  if (rc)
    return rc;

  for (i = 0; i < MD5LEN; i++)
    {
      a2hexhash[2 * i + 1] = HEXCHAR (hash[i]);
      a2hexhash[2 * i + 0] = HEXCHAR (hash[i] >> 4);
    }

  /* response_value */

  sprintf (nchex, "%08lx", nc);

  tmplen = 2 * MD5LEN + strlen (COLON) + strlen (nonce) + strlen (COLON) +
    strlen (nchex) + strlen (COLON) + strlen (cnonce) + strlen (COLON);
  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
    tmplen += strlen (QOP_AUTH_CONF);
  else if (qop & DIGEST_MD5_QOP_AUTH_INT)
    tmplen += strlen (QOP_AUTH_INT);
  else if (qop & DIGEST_MD5_QOP_AUTH)
    tmplen += strlen (QOP_AUTH);
  tmplen += strlen (COLON) + 2 * MD5LEN;

  p = tmp = malloc (tmplen);
  if (tmp == NULL)
    return -1;

  memcpy (p, a1hexhash, 2 * MD5LEN);
  p += 2 * MD5LEN;
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, nonce, strlen (nonce));
  p += strlen (nonce);
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, nchex, strlen (nchex));
  p += strlen (nchex);
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, cnonce, strlen (cnonce));
  p += strlen (cnonce);
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
    {
      memcpy (p, QOP_AUTH_CONF, strlen (QOP_AUTH_CONF));
      p += strlen (QOP_AUTH_CONF);
    }
  else if (qop & DIGEST_MD5_QOP_AUTH_INT)
    {
      memcpy (p, QOP_AUTH_INT, strlen (QOP_AUTH_INT));
      p += strlen (QOP_AUTH_INT);
    }
  else if (qop & DIGEST_MD5_QOP_AUTH)
    {
      memcpy (p, QOP_AUTH, strlen (QOP_AUTH));
      p += strlen (QOP_AUTH);
    }
  memcpy (p, COLON, strlen (COLON));
  p += strlen (COLON);
  memcpy (p, a2hexhash, 2 * MD5LEN);

  rc = gc_md5 (tmp, tmplen, hash);
  free (tmp);
  if (rc)
    return rc;

  for (i = 0; i < MD5LEN; i++)
    {
      output[2 * i + 1] = HEXCHAR (hash[i]);
      output[2 * i + 0] = HEXCHAR (hash[i] >> 4);
    }

  return 0;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]