changeset 12:c778455fe570

Diffie-Hellman seems to be working
author Adam Chlipala <adam@chlipala.net>
date Sat, 01 Jan 2011 14:00:52 -0500
parents e637249abfd2
children de04a3fc6b72
files include/openid.h src/c/openid.c src/ur/openid.ur src/ur/openidFfi.urs
diffstat 4 files changed, 71 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/include/openid.h	Wed Dec 29 16:25:32 2010 -0500
+++ b/include/openid.h	Sat Jan 01 14:00:52 2011 -0500
@@ -24,8 +24,11 @@
 uw_OpenidFfi_outputs uw_OpenidFfi_direct(uw_context, uw_Basis_string url, uw_OpenidFfi_inputs);
 uw_OpenidFfi_outputs uw_OpenidFfi_indirect(uw_context, uw_Basis_string fields);
 
-uw_Basis_string uw_OpenidFfi_sha1(uw_context, uw_Basis_string key, uw_Basis_string data);
-uw_Basis_string uw_OpenidFfi_sha256(uw_context, uw_Basis_string key, uw_Basis_string data);
+uw_Basis_string uw_OpenidFfi_sha1(uw_context ctx, uw_Basis_string data);
+uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string data);
+
+uw_Basis_string uw_OpenidFfi_hmac_sha1(uw_context, uw_Basis_string key, uw_Basis_string data);
+uw_Basis_string uw_OpenidFfi_hmac_sha256(uw_context, uw_Basis_string key, uw_Basis_string data);
 
 typedef DH *uw_OpenidFfi_dh;
 
@@ -35,3 +38,4 @@
 
 uw_OpenidFfi_dh uw_OpenidFfi_generate(uw_context);
 uw_Basis_string uw_OpenidFfi_compute(uw_context, uw_OpenidFfi_dh, uw_Basis_string server_pub);
+uw_Basis_string uw_OpenidFfi_xor(uw_context, uw_Basis_string, uw_Basis_string);
--- a/src/c/openid.c	Wed Dec 29 16:25:32 2010 -0500
+++ b/src/c/openid.c	Sat Jan 01 14:00:52 2011 -0500
@@ -313,7 +313,7 @@
   return n;
 }
 
-uw_Basis_string uw_OpenidFfi_sha1(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
+uw_Basis_string uw_OpenidFfi_hmac_sha1(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
   unsigned char keyBin[SHA_DIGEST_LENGTH], out[EVP_MAX_MD_SIZE];
   unsigned outLen;
 
@@ -323,7 +323,7 @@
   return base64(ctx, out, outLen);
 }
 
-uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
+uw_Basis_string uw_OpenidFfi_hmac_sha256(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
   unsigned char keyBin[SHA256_DIGEST_LENGTH], out[EVP_MAX_MD_SIZE];
   unsigned outLen;
 
@@ -393,16 +393,56 @@
 
 uw_Basis_string uw_OpenidFfi_compute(uw_context ctx, uw_OpenidFfi_dh dh, uw_Basis_string server_pub) {
   BIGNUM *bn = unbtwoc(ctx, server_pub);
-  unsigned char secret[DH_size(dh)];
+  unsigned char secret[DH_size(dh)+1], *secretP;
   int size;
 
   uw_push_cleanup(ctx, (void (*)(void *))BN_free, bn);
 
-  size = DH_compute_key(secret, bn, dh);
+  size = DH_compute_key(secret+1, bn, dh);
   if (size == -1)
     uw_error(ctx, FATAL, "Diffie-Hellman key computation failed");
 
   uw_pop_cleanup(ctx);
 
-  return base64(ctx, secret, size);
+  if (size > 0 && (secret[1] & 0x80)) {
+    secret[0] = 0;
+    secretP = secret;
+    ++size;
+  } else
+    secretP = secret+1;
+
+  return base64(ctx, secretP, size);
 }
+
+uw_Basis_string uw_OpenidFfi_sha1(uw_context ctx, uw_Basis_string data) {
+  unsigned char dataBin[128], out[EVP_MAX_MD_SIZE];
+  int len;
+
+  len = unbase64((unsigned char *)data, strlen(data), dataBin, sizeof dataBin);
+
+  SHA1(dataBin, len, out);
+  return base64(ctx, out, SHA_DIGEST_LENGTH);
+}
+
+uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string data) {
+  unsigned char dataBin[128], out[EVP_MAX_MD_SIZE];
+  int len;
+
+  len = unbase64((unsigned char *)data, strlen(data), dataBin, sizeof dataBin);
+  
+  SHA256(dataBin, len, out);
+  return base64(ctx, out, SHA256_DIGEST_LENGTH);
+}
+
+uw_Basis_string uw_OpenidFfi_xor(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
+  unsigned char buf1[128], buf2[128], bufO[128];
+  int len1, len2, i;
+
+  len1 = unbase64((unsigned char *)s1, strlen(s1), buf1, sizeof buf1);
+  len2 = unbase64((unsigned char *)s2, strlen(s2), buf2, sizeof buf2);
+
+  for (i = 0; i < len1; ++i)
+    bufO[i] = buf1[i] ^ buf2[i % len2];
+
+  return base64(ctx, bufO, len1);
+}
--- a/src/ur/openid.ur	Wed Dec 29 16:25:32 2010 -0500
+++ b/src/ur/openid.ur	Sat Jan 01 14:00:52 2011 -0500
@@ -140,7 +140,12 @@
                 (case read expires of
                      None => return (AssError "Invalid 'expires_in' field")
                    | Some expires =>
-                     key <- OpenidFfi.compute dh pub;
+                     secret <- OpenidFfi.compute dh pub;
+                     digest <- return (case stype of
+                                           DH_SHA1 => OpenidFfi.sha1 secret
+                                         | DH_SHA256 => OpenidFfi.sha256 secret
+                                         | _ => error <xml>Non-DH stype in associateDh</xml>);
+                     key <- return (OpenidFfi.xor mac digest);
                      tm <- now;
                      dml (INSERT INTO associations (Endpoint, Handle, Typ, Key, Expires)
                           VALUES ({[url]}, {[handle]}, {[serialize atype]}, {[key]}, {[addSeconds tm expires]}));
@@ -177,6 +182,7 @@
             if alt.Atype = atype && alt.Stype = stype then
                 return (AssError "Suggested new modes match old ones!")
             else
+                debug "Renegotiating protocol";
                 newAssociation url alt.Atype alt.Stype
           | v => return v
 
@@ -273,8 +279,8 @@
                   | Some ([], nvps) =>
                     let
                         val sign' = case atype of
-                                        HMAC_SHA256 => OpenidFfi.sha256 key nvps
-                                      | HMAC_SHA1 => OpenidFfi.sha1 key nvps
+                                        HMAC_SHA256 => OpenidFfi.hmac_sha256 key nvps
+                                      | HMAC_SHA1 => OpenidFfi.hmac_sha1 key nvps
                     in
                         (*debug ("Fields: " ^ signed);
                         debug ("Nvps: " ^ nvps);
@@ -291,11 +297,9 @@
 
 datatype authentication = AuthenticatedAs of string | Canceled | Failure of string
 
-sequence nextNonce
-
 fun authenticate after r =
     let
-        fun returnTo myNonce (qs : option queryString) =
+        fun returnTo (qs : option queryString) =
             case qs of
                 None => after (Failure "Empty query string for OpenID callback")
               | Some qs =>
@@ -316,7 +320,7 @@
                                  case errO of
                                      HandleError s => after (Failure s)
                                    | HandleOk {Endpoint = ep, Typ = atype, Key = key} =>
-                                     errO <- verifyReturnTo os myNonce;
+                                     errO <- verifyReturnTo os;
                                      case errO of
                                          Some s => after (Failure s)
                                        | None =>
@@ -330,11 +334,11 @@
                                                | None => after (AuthenticatedAs id))
                           | _ => after (Failure ("Unexpected openid.mode: " ^ mode))
 
-        and verifyReturnTo os myNonce =
+        and verifyReturnTo os =
             case OpenidFfi.getOutput os "openid.return_to" of
                 None => return (Some "Missing return_to in OP response")
               | Some rt =>
-                if rt <> show (effectfulUrl (returnTo myNonce)) then
+                if rt <> show (effectfulUrl returnTo) then
                     return (Some "Wrong return_to in OP response")
                 else
                     return None
@@ -348,10 +352,9 @@
                 AssError msg => return ("Association failure: " ^ msg)
               | AssAlternate _ => return "Association failure: server didn't accept its own alternate association modes"
               | Association assoc =>
-                myNonce <- nextval nextNonce;
                 redirect (bless (dy ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.claimed_id="
                                  ^ r.Identifier ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.assoc_handle="
-                                 ^ assoc.Handle ^ "&openid.return_to=" ^ show (effectfulUrl (returnTo myNonce))))
+                                 ^ assoc.Handle ^ "&openid.return_to=" ^ show (effectfulUrl returnTo)))
     end
 
 task periodic 1 = fn () =>
--- a/src/ur/openidFfi.urs	Wed Dec 29 16:25:32 2010 -0500
+++ b/src/ur/openidFfi.urs	Sat Jan 01 14:00:52 2011 -0500
@@ -15,8 +15,11 @@
 val direct : string -> inputs -> transaction outputs
 val indirect : queryString -> transaction outputs
 
-val sha1 : string -> string -> string
-val sha256 : string -> string -> string
+val sha1 : string -> string
+val sha256 : string -> string
+
+val hmac_sha1 : string -> string -> string
+val hmac_sha256 : string -> string -> string
 
 type dh
 val modulus : dh -> string
@@ -25,3 +28,4 @@
 
 val generate : transaction dh
 val compute : dh -> string -> transaction string
+val xor : string -> string -> string