]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanservcrypto.c
Add challengeauth support, refactor challenge stuff.
[irc/quakenet/newserv.git] / chanserv / chanservcrypto.c
1 #include <stdio.h>
2
3 #include "chanserv.h"
4 #include "../core/error.h"
5 #include "../lib/prng.h"
6 #include "../lib/sha1.h"
7 #include "../lib/sha2.h"
8 #include "../lib/md5.h"
9 #include "../lib/hmac.h"
10
11 prngctx rng;
12
13 void chanservcryptoinit(void) {
14 int ret;
15
16 FILE *e = fopen(ENTROPYSOURCE, "rb");
17 if(!e) {
18 Error("chanserv",ERR_STOP,"Unable to open entropy source.");
19 /* shouldn't be running now... */
20 }
21
22 ret = fread(rng.randrsl, 1, sizeof(rng.randrsl), e);
23 fclose(e);
24
25 if(ret != sizeof(rng.randrsl)) {
26 Error("chanserv",ERR_STOP,"Unable to read entropy.");
27 /* shouldn't be running now... */
28 }
29
30 prnginit(&rng, 1);
31 }
32
33 ub4 cs_getrandint(void) {
34 return prng(&rng);
35 }
36
37 void cs_getrandbytes(unsigned char *buf, size_t bytes) {
38 for(;bytes>0;bytes-=4,buf+=4) {
39 ub4 b = cs_getrandint();
40 memcpy(buf, &b, 4);
41 }
42 }
43
44 const char *cs_cralgorithmlist(void) {
45 return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256";
46 }
47
48 int crsha1(char *username, const char *password, const char *challenge, const char *response) {
49 char buf[1024];
50
51 SHA1_CTX ctx;
52 unsigned char digest[20];
53 char hexbuf[sizeof(digest) * 2 + 1];
54 hmacsha1 hmac;
55
56 /* not sure how this helps but the RFC says to do it... */
57 SHA1Init(&ctx);
58 SHA1Update(&ctx, (unsigned char *)password, strlen(password));
59 SHA1Final(digest, &ctx);
60
61 snprintf(buf, sizeof(buf), "%s:%s", username, hmac_printhex(digest, hexbuf, sizeof(digest)));
62
63 SHA1Init(&ctx);
64 SHA1Update(&ctx, (unsigned char *)buf, strlen(buf));
65 SHA1Final(digest, &ctx);
66
67 hmacsha1_init(&hmac, (unsigned char *)hmac_printhex(digest, hexbuf, sizeof(digest)), sizeof(digest) * 2);
68 hmacsha1_update(&hmac, (unsigned char *)challenge, strlen(challenge));
69 hmacsha1_final(&hmac, digest);
70
71 hmac_printhex(digest, hexbuf, sizeof(digest));
72
73 if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
74 return 1;
75
76 return 0;
77 }
78
79 int crsha256(char *username, const char *password, const char *challenge, const char *response) {
80 char buf[1024];
81
82 SHA256_CTX ctx;
83 unsigned char digest[32];
84 char hexbuf[sizeof(digest) * 2 + 1];
85 hmacsha256 hmac;
86
87 /* not sure how this helps but the RFC says to do it... */
88 SHA256_Init(&ctx);
89 SHA256_Update(&ctx, (unsigned char *)password, strlen(password));
90 SHA256_Final(digest, &ctx);
91
92 snprintf(buf, sizeof(buf), "%s:%s", username, hmac_printhex(digest, hexbuf, sizeof(digest)));
93
94 SHA256_Init(&ctx);
95 SHA256_Update(&ctx, (unsigned char *)buf, strlen(buf));
96 SHA256_Final(digest, &ctx);
97
98 hmacsha256_init(&hmac, (unsigned char *)hmac_printhex(digest, hexbuf, sizeof(digest)), sizeof(digest) * 2);
99 hmacsha256_update(&hmac, (unsigned char *)challenge, strlen(challenge));
100 hmacsha256_final(&hmac, digest);
101
102 if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
103 return 1;
104
105 return 0;
106 }
107
108 int crmd5(char *username, const char *password, const char *challenge, const char *response) {
109 char buf[1024];
110
111 MD5Context ctx;
112 unsigned char digest[16];
113 char hexbuf[sizeof(digest) * 2 + 1];
114 hmacmd5 hmac;
115
116 /* not sure how this helps but the RFC says to do it... */
117 MD5Init(&ctx);
118 MD5Update(&ctx, (unsigned char *)password, strlen(password));
119 MD5Final(digest, &ctx);
120
121 snprintf(buf, sizeof(buf), "%s:%s", username, hmac_printhex(digest, hexbuf, sizeof(digest)));
122
123 MD5Init(&ctx);
124 MD5Update(&ctx, (unsigned char *)buf, strlen(buf));
125 MD5Final(digest, &ctx);
126
127 hmacmd5_init(&hmac, (unsigned char *)hmac_printhex(digest, hexbuf, sizeof(digest)), sizeof(digest) * 2);
128 hmacmd5_update(&hmac, (unsigned char *)challenge, strlen(challenge));
129 hmacmd5_final(&hmac, digest);
130
131 if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response))
132 return 1;
133
134 return 0;
135 }
136
137 CRAlgorithm cs_cralgorithm(const char *algorithm) {
138 if(!strcasecmp(algorithm, "hmac-sha-1"))
139 return crsha1;
140
141 if(!strcasecmp(algorithm, "hmac-sha-256"))
142 return crsha256;
143
144 if(!strcasecmp(algorithm, "hmac-md5"))
145 return crmd5;
146
147 return 0;
148 }
149
150 char *cs_calcchallenge(const unsigned char *entropy) {
151 unsigned char buf[20];
152 static char hexbuf[sizeof(buf) * 2 + 1];
153 SHA1_CTX ctx;
154
155 SHA1Init(&ctx);
156 /* we can maybe add a salt here in the future */
157 SHA1Update(&ctx, entropy, ENTROPYLEN);
158 SHA1Final(buf, &ctx);
159
160 hmac_printhex(buf, hexbuf, sizeof(buf));
161
162 return hexbuf;
163 }