]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanservcrypto.c
5 #include "../core/error.h"
6 #include "../core/config.h"
7 #include "../lib/prng.h"
8 #include "../lib/sha1.h"
9 #include "../lib/sha2.h"
10 #include "../lib/md5.h"
11 #include "../lib/hmac.h"
14 static sstring
*secret
, *codesecret
;
16 static sstring
*combinesecret(char *str
) {
18 unsigned char digest
[32];
19 char hexbuf
[sizeof(digest
) * 2 + 1];
22 SHA256_Update(&ctx
, (unsigned char *)secret
->content
, secret
->length
);
23 SHA256_Update(&ctx
, (unsigned char *)":", 1);
24 SHA256_Update(&ctx
, (unsigned char *)str
, strlen(str
));
25 SHA256_Final(digest
, &ctx
);
28 SHA256_Update(&ctx
, digest
, sizeof(digest
));
29 SHA256_Final(digest
, &ctx
);
30 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
32 return getsstring(hexbuf
, strlen(hexbuf
));
35 void chanservcryptoinit(void) {
38 FILE *e
= fopen(ENTROPYSOURCE
, "rb");
40 Error("chanserv",ERR_STOP
,"Unable to open entropy source.");
41 /* shouldn't be running now... */
44 ret
= fread(rng
.randrsl
, 1, sizeof(rng
.randrsl
), e
);
47 if(ret
!= sizeof(rng
.randrsl
)) {
48 Error("chanserv",ERR_STOP
,"Unable to read entropy.");
49 /* shouldn't be running now... */
54 secret
=getcopyconfigitem("chanserv","secret","",128);
55 if(!secret
|| !secret
->content
|| !secret
->content
[0]) {
56 unsigned char buf
[32];
57 char hexbuf
[sizeof(buf
) * 2 + 1];
59 Error("chanserv",ERR_WARNING
,"Shared secret not set, generating a random string...");
61 cs_getrandbytes(buf
, 32);
62 hmac_printhex(buf
, hexbuf
, sizeof(buf
));
63 secret
=getsstring(hexbuf
, strlen(hexbuf
));
65 codesecret
=combinesecret("codegenerator");
69 void chanservcryptofree(void) {
71 freesstring(codesecret
);
74 ub4
cs_getrandint(void) {
78 void cs_getrandbytes(unsigned char *buf
, size_t bytes
) {
79 for(;bytes
>0;bytes
-=4,buf
+=4) {
80 ub4 b
= cs_getrandint();
85 const char *cs_cralgorithmlist(void) {
86 return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256 LEGACY-MD5";
89 int crsha1(char *username
, const char *password
, const char *challenge
, const char *response
) {
93 unsigned char digest
[20];
94 char hexbuf
[sizeof(digest
) * 2 + 1];
97 /* not sure how this helps but the RFC says to do it... */
99 SHA1Update(&ctx
, (unsigned char *)password
, strlen(password
));
100 SHA1Final(digest
, &ctx
);
102 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
105 SHA1Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
106 SHA1Final(digest
, &ctx
);
108 hmacsha1_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
109 hmacsha1_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
110 hmacsha1_final(&hmac
, digest
);
112 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
114 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
120 int crsha256(char *username
, const char *password
, const char *challenge
, const char *response
) {
124 unsigned char digest
[32];
125 char hexbuf
[sizeof(digest
) * 2 + 1];
128 /* not sure how this helps but the RFC says to do it... */
130 SHA256_Update(&ctx
, (unsigned char *)password
, strlen(password
));
131 SHA256_Final(digest
, &ctx
);
133 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
136 SHA256_Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
137 SHA256_Final(digest
, &ctx
);
139 hmacsha256_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
140 hmacsha256_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
141 hmacsha256_final(&hmac
, digest
);
143 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
149 int crmd5(char *username
, const char *password
, const char *challenge
, const char *response
) {
153 unsigned char digest
[16];
154 char hexbuf
[sizeof(digest
) * 2 + 1];
157 /* not sure how this helps but the RFC says to do it... */
159 MD5Update(&ctx
, (unsigned char *)password
, strlen(password
));
160 MD5Final(digest
, &ctx
);
162 snprintf(buf
, sizeof(buf
), "%s:%s", username
, hmac_printhex(digest
, hexbuf
, sizeof(digest
)));
165 MD5Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
166 MD5Final(digest
, &ctx
);
168 hmacmd5_init(&hmac
, (unsigned char *)hmac_printhex(digest
, hexbuf
, sizeof(digest
)), sizeof(digest
) * 2);
169 hmacmd5_update(&hmac
, (unsigned char *)challenge
, strlen(challenge
));
170 hmacmd5_final(&hmac
, digest
);
172 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
178 int crlegacymd5(char *username
, const char *password
, const char *challenge
, const char *response
) {
180 unsigned char digest
[16];
181 char hexbuf
[sizeof(digest
) * 2 + 1];
184 MD5Update(&ctx
, (unsigned char *)password
, strlen(password
));
185 MD5Update(&ctx
, (unsigned char *)" ", 1);
186 MD5Update(&ctx
, (unsigned char *)challenge
, strlen(challenge
));
187 MD5Final(digest
, &ctx
);
189 if(!strcasecmp(hmac_printhex(digest
, hexbuf
, sizeof(digest
)), response
))
195 CRAlgorithm
cs_cralgorithm(const char *algorithm
) {
196 if(!strcasecmp(algorithm
, "hmac-sha-1"))
199 if(!strcasecmp(algorithm
, "hmac-sha-256"))
202 if(!strcasecmp(algorithm
, "hmac-md5"))
205 if(!strcasecmp(algorithm
, "legacy-md5"))
211 char *cs_calcchallenge(const unsigned char *entropy
) {
212 unsigned char buf
[20];
213 static char hexbuf
[sizeof(buf
) * 2 + 1];
217 /* we can maybe add a salt here in the future */
218 SHA1Update(&ctx
, entropy
, ENTROPYLEN
);
219 SHA1Final(buf
, &ctx
);
221 hmac_printhex(buf
, hexbuf
, 16);
226 int cs_checkhashpass(const char *username
, const char *password
, const char *junk
, const char *hash
) {
228 unsigned char digest
[16];
229 char hexbuf
[sizeof(digest
) * 2 + 1], buf
[512];
231 snprintf(buf
, sizeof(buf
), "%s %s%s%s", username
, password
, junk
?" ":"", junk
?junk
:"");
234 MD5Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
235 MD5Final(digest
, &ctx
);
237 if(strcasecmp(hash
, hmac_printhex(digest
, hexbuf
, sizeof(digest
))))
243 char *csc_generateresetcode(time_t lockuntil
, char *username
) {
244 unsigned char digest
[32];
245 static char hexbuf
[sizeof(digest
) * 2 + 1];
250 snprintf(buf
, sizeof(buf
), "%s:%lu", username
, lockuntil
);
253 SHA256_Update(&ctx
, (unsigned char *)buf
, strlen(buf
));
254 SHA256_Final(digest
, &ctx
);
256 hmac_printhex(digest
, hexbuf
, sizeof(digest
));
258 hmacsha256_init(&hmac
, (unsigned char *)codesecret
->content
, codesecret
->length
);
259 hmacsha256_update(&hmac
, (unsigned char *)hexbuf
, strlen(hexbuf
));
260 hmacsha256_final(&hmac
, digest
);
262 hmac_printhex(digest
, hexbuf
, sizeof(digest
));