]> jfr.im git - irc/quakenet/newserv.git/blame - chanserv/chanservcrypto.c
Chanlev can now take the +n flag, but not give it.
[irc/quakenet/newserv.git] / chanserv / chanservcrypto.c
CommitLineData
0ba70e7b
CP
1#include <stdio.h>
2
3#include "chanserv.h"
4#include "../core/error.h"
5#include "../lib/prng.h"
b7a95f03
CP
6#include "../lib/sha1.h"
7#include "../lib/sha2.h"
8#include "../lib/md5.h"
9#include "../lib/hmac.h"
0ba70e7b
CP
10
11prngctx rng;
12
13void 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
33ub4 cs_getrandint(void) {
34 return prng(&rng);
35}
36
37void cs_getrandbytes(unsigned char *buf, size_t bytes) {
45770ae6 38 for(;bytes>0;bytes-=4,buf+=4) {
0ba70e7b 39 ub4 b = cs_getrandint();
45770ae6 40 memcpy(buf, &b, 4);
0ba70e7b
CP
41 }
42}
b7a95f03
CP
43
44const char *cs_cralgorithmlist(void) {
45 return "HMAC-MD5 HMAC-SHA-1 HMAC-SHA-256";
46}
47
48int 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
79int 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
108int 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
137CRAlgorithm 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
150char *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}