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