# HG changeset patch # User Adam Chlipala # Date 1293908452 18000 # Node ID c778455fe57070e6c35de8232bb9cc26349b0ea7 # Parent e637249abfd26a5e24561c2ab6497555af1f13bb Diffie-Hellman seems to be working diff -r e637249abfd2 -r c778455fe570 include/openid.h --- 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); diff -r e637249abfd2 -r c778455fe570 src/c/openid.c --- 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); +} diff -r e637249abfd2 -r c778455fe570 src/ur/openid.ur --- 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 Non-DH stype in associateDh); + 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 () => diff -r e637249abfd2 -r c778455fe570 src/ur/openidFfi.urs --- 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