]> code.citadel.org Git - citadel.git/blob - rss2ctdl/digcalc.c
4114c0626a73f6bc4e2ff03da3185291c13e969b
[citadel.git] / rss2ctdl / digcalc.c
1 /*
2  * $Id$
3  * 
4  * Copyright 2003-2004 Oliver Feiler <kiza@kcore.de>
5  *
6  * digcalc.c
7  *
8  * This is the sample implementation from RFC 2617.
9  * The code has been modified to work with Colin Plumb's
10  * MD5 implementation rather than using RSA's.
11  */
12
13 #include "md5.h"
14
15 #include <string.h>
16 #include "digcalc.h"
17
18 void CvtHex(
19     IN HASH Bin,
20     OUT HASHHEX Hex
21     )
22 {
23     unsigned short i;
24     unsigned char j;
25
26     for (i = 0; i < HASHLEN; i++) {
27         j = (Bin[i] >> 4) & 0xf;
28         if (j <= 9)
29             Hex[i*2] = (j + '0');
30          else
31             Hex[i*2] = (j + 'a' - 10);
32         j = Bin[i] & 0xf;
33         if (j <= 9)
34             Hex[i*2+1] = (j + '0');
35          else
36             Hex[i*2+1] = (j + 'a' - 10);
37     };
38     Hex[HASHHEXLEN] = '\0';
39 };
40
41 /* calculate H(A1) as per spec */
42 void DigestCalcHA1(
43     IN char * pszAlg,
44     IN char * pszUserName,
45     IN char * pszRealm,
46     IN char * pszPassword,
47     IN char * pszNonce,
48     IN char * pszCNonce,
49     OUT HASHHEX SessionKey
50     )
51 {
52       struct MD5Context Md5Ctx;
53       HASH HA1;
54
55       MD5Init(&Md5Ctx);
56       MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
57       MD5Update(&Md5Ctx, ":", 1);
58       MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm));
59       MD5Update(&Md5Ctx, ":", 1);
60       MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword));
61       MD5Final(HA1, &Md5Ctx);
62       if (strcmp(pszAlg, "md5-sess") == 0) {
63
64             MD5Init(&Md5Ctx);
65             MD5Update(&Md5Ctx, HA1, HASHLEN);
66             MD5Update(&Md5Ctx, ":", 1);
67             MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
68             MD5Update(&Md5Ctx, ":", 1);
69             MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
70             MD5Final(HA1, &Md5Ctx);
71       };
72       CvtHex(HA1, SessionKey);
73 };
74
75 /* calculate request-digest/response-digest as per HTTP Digest spec */
76 void DigestCalcResponse(
77     IN HASHHEX HA1,           /* H(A1) */
78     IN char * pszNonce,       /* nonce from server */
79     IN char * pszNonceCount,  /* 8 hex digits */
80     IN char * pszCNonce,      /* client nonce */
81     IN char * pszQop,         /* qop-value: "", "auth", "auth-int" */
82     IN char * pszMethod,      /* method from the request */
83     IN char * pszDigestUri,   /* requested URL */
84     IN HASHHEX HEntity,       /* H(entity body) if qop="auth-int" */
85     OUT HASHHEX Response      /* request-digest or response-digest */
86     )
87 {
88       struct MD5Context Md5Ctx;
89       HASH HA2;
90       HASH RespHash;
91        HASHHEX HA2Hex;
92
93       /* calculate H(A2) */
94       MD5Init(&Md5Ctx);
95       MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod));
96       MD5Update(&Md5Ctx, ":", 1);
97       MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri));
98       if (strcmp(pszQop, "auth-int") == 0) {
99             MD5Update(&Md5Ctx, ":", 1);
100             MD5Update(&Md5Ctx, HEntity, HASHHEXLEN);
101       };
102       MD5Final(HA2, &Md5Ctx);
103        CvtHex(HA2, HA2Hex);
104
105       /* calculate response */
106       MD5Init(&Md5Ctx);
107       MD5Update(&Md5Ctx, HA1, HASHHEXLEN);
108       MD5Update(&Md5Ctx, ":", 1);
109       MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
110       MD5Update(&Md5Ctx, ":", 1);
111       if (*pszQop) {
112
113           MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount));
114           MD5Update(&Md5Ctx, ":", 1);
115           MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
116           MD5Update(&Md5Ctx, ":", 1);
117           MD5Update(&Md5Ctx, pszQop, strlen(pszQop));
118           MD5Update(&Md5Ctx, ":", 1);
119       };
120       MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN);
121       MD5Final(RespHash, &Md5Ctx);
122       CvtHex(RespHash, Response);
123 };