]>
Commit | Line | Data |
---|---|---|
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 | |
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) { | |
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 | |
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 | } |