adam@14
|
1 #include <ctype.h>
|
adam@1
|
2 #include <string.h>
|
adam@1
|
3
|
adam@6
|
4 #include <openssl/bio.h>
|
adam@6
|
5 #include <openssl/evp.h>
|
adam@6
|
6 #include <openssl/buffer.h>
|
adam@0
|
7 #include <openssl/sha.h>
|
adam@7
|
8 #include <openssl/hmac.h>
|
adam@8
|
9 #include <openssl/dh.h>
|
adam@0
|
10 #include <curl/curl.h>
|
adam@1
|
11 #include <expat.h>
|
adam@0
|
12
|
adam@1
|
13 #include <openid.h>
|
adam@0
|
14
|
adam@3
|
15 #define BUF_MAX 10240
|
adam@3
|
16 #define BUF_INIT 1024
|
adam@3
|
17
|
adam@8
|
18 #define PRIME_LEN 64
|
adam@8
|
19 #define GENERATOR DH_GENERATOR_5
|
adam@2
|
20
|
adam@2
|
21 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) {
|
adam@8
|
22 return d.endpoint;
|
adam@2
|
23 }
|
adam@2
|
24
|
adam@2
|
25 uw_Basis_string uw_OpenidFfi_localId(uw_context ctx, uw_OpenidFfi_discovery d) {
|
adam@8
|
26 return d.localId;
|
adam@2
|
27 }
|
adam@2
|
28
|
adam@0
|
29 uw_unit uw_OpenidFfi_init(uw_context ctx) {
|
adam@0
|
30 curl_global_init(CURL_GLOBAL_ALL);
|
adam@0
|
31
|
adam@0
|
32 return uw_unit_v;
|
adam@0
|
33 }
|
adam@1
|
34
|
adam@1
|
35 static CURL *curl(uw_context ctx) {
|
adam@1
|
36 CURL *r;
|
adam@1
|
37
|
adam@1
|
38 if (!(r = uw_get_global(ctx, "curl"))) {
|
adam@1
|
39 r = curl_easy_init();
|
adam@1
|
40 if (r)
|
adam@1
|
41 uw_set_global(ctx, "curl", r, curl_easy_cleanup);
|
adam@1
|
42 }
|
adam@1
|
43
|
adam@1
|
44 return r;
|
adam@1
|
45 }
|
adam@1
|
46
|
adam@1
|
47 typedef struct {
|
adam@1
|
48 uw_context ctx;
|
adam@8
|
49 uw_OpenidFfi_discovery *d;
|
adam@1
|
50 } endpoint;
|
adam@1
|
51
|
adam@1
|
52 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
|
adam@1
|
53 endpoint *ep = userData;
|
adam@1
|
54
|
adam@1
|
55 if (!strcmp(name, "link")) {
|
adam@1
|
56 const XML_Char **attp;
|
adam@1
|
57 int found = 0;
|
adam@1
|
58
|
adam@1
|
59 for (attp = atts; *attp; attp += 2) {
|
adam@1
|
60 if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) {
|
adam@1
|
61 found = 1;
|
adam@1
|
62 break;
|
adam@1
|
63 }
|
adam@1
|
64 }
|
adam@1
|
65
|
adam@1
|
66 if (found) {
|
adam@1
|
67 for (attp = atts; *attp; attp += 2) {
|
adam@1
|
68 if (!strcmp(attp[0], "href")) {
|
adam@2
|
69 ep->d->endpoint = uw_strdup(ep->ctx, attp[1]);
|
adam@1
|
70 return;
|
adam@1
|
71 }
|
adam@1
|
72 }
|
adam@1
|
73 }
|
adam@1
|
74 }
|
adam@1
|
75 }
|
adam@1
|
76
|
adam@1
|
77 typedef struct {
|
adam@1
|
78 XML_Parser parser;
|
adam@1
|
79 int any_errors;
|
adam@3
|
80 } curl_discovery_data;
|
adam@1
|
81
|
adam@3
|
82 static size_t write_discovery_data(void *buffer, size_t size, size_t nmemb, void *userp) {
|
adam@3
|
83 curl_discovery_data *d = userp;
|
adam@1
|
84
|
adam@1
|
85 if (!XML_Parse(d->parser, buffer, size * nmemb, 0))
|
adam@1
|
86 d->any_errors = 1;
|
adam@1
|
87
|
adam@1
|
88 return size * nmemb;
|
adam@1
|
89 }
|
adam@1
|
90
|
adam@2
|
91 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) {
|
adam@1
|
92 char *s;
|
adam@1
|
93 CURL *c = curl(ctx);
|
adam@3
|
94 curl_discovery_data cd = {};
|
adam@8
|
95 uw_OpenidFfi_discovery *dy = uw_malloc(ctx, sizeof(uw_OpenidFfi_discovery));
|
adam@2
|
96 endpoint ep = {ctx, dy};
|
adam@1
|
97 CURLcode code;
|
adam@1
|
98
|
adam@2
|
99 dy->endpoint = dy->localId = NULL;
|
adam@2
|
100
|
adam@1
|
101 if (!strchr(id, ':')) {
|
adam@1
|
102 id = uw_Basis_strcat(ctx, "http://", id);
|
adam@1
|
103 if ((s = strchr(id, '#')) != NULL)
|
adam@1
|
104 *s = 0;
|
adam@1
|
105 } else if ((s = strchr(id, '#')) != NULL) {
|
adam@1
|
106 char *id2 = uw_malloc(ctx, s - id + 1);
|
adam@1
|
107 memcpy(id2, s, s - id);
|
adam@1
|
108 id2[s - id] = 0;
|
adam@1
|
109 id = id2;
|
adam@1
|
110 }
|
adam@1
|
111
|
adam@1
|
112 cd.parser = XML_ParserCreate(NULL);
|
adam@1
|
113 XML_SetUserData(cd.parser, &ep);
|
adam@1
|
114 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
|
adam@7
|
115 XML_SetStartElementHandler(cd.parser, startElement);
|
adam@1
|
116
|
adam@1
|
117 curl_easy_setopt(c, CURLOPT_URL, id);
|
adam@3
|
118 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data);
|
adam@1
|
119 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
|
adam@1
|
120
|
adam@1
|
121 code = curl_easy_perform(c);
|
adam@1
|
122 uw_pop_cleanup(ctx);
|
adam@1
|
123
|
adam@8
|
124 if (code || !dy->endpoint)
|
adam@1
|
125 return NULL;
|
adam@8
|
126 else
|
adam@8
|
127 return dy;
|
adam@1
|
128 }
|
adam@3
|
129
|
adam@3
|
130 uw_OpenidFfi_inputs uw_OpenidFfi_createInputs(uw_context ctx) {
|
adam@3
|
131 uw_buffer *r = uw_malloc(ctx, sizeof(uw_buffer));
|
adam@3
|
132 uw_buffer_init(BUF_MAX, r, BUF_INIT);
|
adam@3
|
133 return r;
|
adam@3
|
134 }
|
adam@3
|
135
|
adam@8
|
136 static void postify(uw_OpenidFfi_inputs buf, uw_Basis_string s) {
|
adam@14
|
137 char hex[4];
|
adam@14
|
138
|
adam@8
|
139 for (; *s; ++s) {
|
adam@14
|
140 if (isalnum(*s))
|
adam@14
|
141 uw_buffer_append(buf, s, 1);
|
adam@14
|
142 else {
|
adam@14
|
143 sprintf(hex, "%%%02X", (unsigned char)*s);
|
adam@14
|
144 uw_buffer_append(buf, hex, 3);
|
adam@14
|
145 }
|
adam@14
|
146
|
adam@14
|
147 /*switch (*s) {
|
adam@8
|
148 case '=':
|
adam@8
|
149 uw_buffer_append(buf, "%3D", 3);
|
adam@8
|
150 break;
|
adam@8
|
151 case '&':
|
adam@8
|
152 uw_buffer_append(buf, "%26", 3);
|
adam@8
|
153 break;
|
adam@14
|
154 case '%':
|
adam@14
|
155 uw_buffer_append(buf, "%25", 3);
|
adam@14
|
156 break;
|
adam@8
|
157 default:
|
adam@8
|
158 uw_buffer_append(buf, s, 1);
|
adam@14
|
159 }*/
|
adam@8
|
160 }
|
adam@3
|
161 }
|
adam@3
|
162
|
adam@3
|
163 uw_unit uw_OpenidFfi_addInput(uw_context ctx, uw_OpenidFfi_inputs buf, uw_Basis_string key, uw_Basis_string value) {
|
adam@3
|
164 if (uw_buffer_used(buf) > 0)
|
adam@3
|
165 uw_buffer_append(buf, "&", 1);
|
adam@3
|
166
|
adam@14
|
167 uw_buffer_append(buf, key, strlen(key));
|
adam@3
|
168 uw_buffer_append(buf, "=", 1);
|
adam@8
|
169 postify(buf, value);
|
adam@3
|
170
|
adam@3
|
171 return uw_unit_v;
|
adam@3
|
172 }
|
adam@3
|
173
|
adam@3
|
174 uw_Basis_string uw_OpenidFfi_getOutput(uw_context ctx, uw_OpenidFfi_outputs buf, uw_Basis_string key) {
|
adam@3
|
175 char *s = buf->start;
|
adam@3
|
176
|
adam@3
|
177 for (; *s; s = strchr(strchr(s, 0)+1, 0)+1)
|
adam@3
|
178 if (!strcmp(key, s))
|
adam@3
|
179 return strchr(s, 0)+1;
|
adam@3
|
180
|
adam@3
|
181 return NULL;
|
adam@3
|
182 }
|
adam@3
|
183
|
adam@3
|
184 static size_t write_buffer_data(void *buffer, size_t size, size_t nmemb, void *userp) {
|
adam@3
|
185 uw_buffer *buf = userp;
|
adam@3
|
186
|
adam@3
|
187 uw_buffer_append(buf, buffer, size * nmemb);
|
adam@3
|
188
|
adam@3
|
189 return size * nmemb;
|
adam@3
|
190 }
|
adam@3
|
191
|
adam@3
|
192 const char curl_failure[] = "error\0Error fetching URL";
|
adam@3
|
193
|
adam@4
|
194 uw_OpenidFfi_outputs uw_OpenidFfi_direct(uw_context ctx, uw_Basis_string url, uw_OpenidFfi_inputs inps) {
|
adam@3
|
195 uw_buffer *buf = uw_malloc(ctx, sizeof(uw_buffer));
|
adam@3
|
196 CURL *c = curl(ctx);
|
adam@3
|
197 CURLcode code;
|
adam@3
|
198
|
adam@3
|
199 uw_buffer_init(BUF_MAX, buf, BUF_INIT);
|
adam@3
|
200
|
adam@3
|
201 uw_buffer_append(inps, "", 1);
|
adam@3
|
202
|
adam@3
|
203 curl_easy_setopt(c, CURLOPT_URL, url);
|
adam@3
|
204 curl_easy_setopt(c, CURLOPT_POSTFIELDS, inps->start);
|
adam@3
|
205 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_buffer_data);
|
adam@3
|
206 curl_easy_setopt(c, CURLOPT_WRITEDATA, buf);
|
adam@3
|
207
|
adam@3
|
208 code = curl_easy_perform(c);
|
adam@3
|
209
|
adam@3
|
210 uw_buffer_append(buf, "", 1);
|
adam@3
|
211
|
adam@3
|
212 if (code) {
|
adam@3
|
213 uw_buffer_reset(buf);
|
adam@3
|
214 uw_buffer_append(buf, curl_failure, sizeof curl_failure);
|
adam@3
|
215 } else {
|
adam@3
|
216 char *s;
|
adam@3
|
217
|
adam@3
|
218 s = buf->start;
|
adam@3
|
219 while (*s) {
|
adam@3
|
220 char *colon = strchr(s, ':'), *newline;
|
adam@3
|
221
|
adam@3
|
222 if (!colon) {
|
adam@3
|
223 *s = 0;
|
adam@3
|
224 break;
|
adam@3
|
225 }
|
adam@3
|
226
|
adam@7
|
227 *colon = 0;
|
adam@7
|
228
|
adam@3
|
229 newline = strchr(colon+1, '\n');
|
adam@3
|
230
|
adam@7
|
231 if (!newline)
|
adam@3
|
232 break;
|
adam@3
|
233
|
adam@3
|
234 *newline = 0;
|
adam@3
|
235 s = newline+1;
|
adam@3
|
236 }
|
adam@3
|
237 }
|
adam@3
|
238
|
adam@3
|
239 return buf;
|
adam@3
|
240 }
|
adam@4
|
241
|
adam@4
|
242 static uw_Basis_string deurl(uw_context ctx, uw_Basis_string s) {
|
adam@4
|
243 uw_Basis_string r = uw_malloc(ctx, strlen(s)), s2 = r;
|
adam@4
|
244
|
adam@4
|
245 for (; *s; ++s) {
|
adam@4
|
246 if (s[0] == '%' && s[1] && s[2]) {
|
adam@4
|
247 unsigned u;
|
adam@4
|
248
|
adam@4
|
249 sscanf(s+1, "%02x", &u);
|
adam@4
|
250 *s2++ = u;
|
adam@4
|
251 s += 2;
|
adam@4
|
252 } else
|
adam@4
|
253 *s2++ = *s;
|
adam@4
|
254 }
|
adam@4
|
255
|
adam@4
|
256 *s2 = 0;
|
adam@4
|
257 return r;
|
adam@4
|
258 }
|
adam@4
|
259
|
adam@4
|
260 uw_OpenidFfi_outputs uw_OpenidFfi_indirect(uw_context ctx, uw_Basis_string fields) {
|
adam@4
|
261 uw_OpenidFfi_outputs b = malloc(sizeof(uw_buffer));
|
adam@4
|
262
|
adam@4
|
263 uw_buffer_init(BUF_MAX, b, BUF_INIT);
|
adam@4
|
264
|
adam@6
|
265 fields = uw_strdup(ctx, fields);
|
adam@6
|
266
|
adam@4
|
267 while (*fields) {
|
adam@4
|
268 char *equal = strchr(fields, '='), *and, *s;
|
adam@4
|
269
|
adam@4
|
270 if (!equal)
|
adam@4
|
271 break;
|
adam@4
|
272
|
adam@4
|
273 *equal = 0;
|
adam@4
|
274 s = deurl(ctx, fields);
|
adam@4
|
275 uw_buffer_append(b, s, strlen(s));
|
adam@4
|
276 uw_buffer_append(b, "", 1);
|
adam@4
|
277
|
adam@4
|
278 and = strchr(equal+1, '&');
|
adam@4
|
279 if (and) {
|
adam@4
|
280 *and = 0;
|
adam@4
|
281 fields = and+1;
|
adam@4
|
282 } else
|
adam@4
|
283 fields = and = strchr(equal+1, 0);
|
adam@4
|
284 s = deurl(ctx, equal+1);
|
adam@4
|
285 uw_buffer_append(b, s, strlen(s));
|
adam@4
|
286 uw_buffer_append(b, "", 1);
|
adam@4
|
287 }
|
adam@4
|
288
|
adam@4
|
289 uw_buffer_append(b, "", 1);
|
adam@4
|
290 return b;
|
adam@4
|
291 }
|
adam@6
|
292
|
adam@6
|
293 static uw_Basis_string base64(uw_context ctx, unsigned char *input, int length) {
|
adam@6
|
294 BIO *bmem, *b64;
|
adam@6
|
295
|
adam@6
|
296 b64 = BIO_new(BIO_f_base64());
|
adam@7
|
297 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
adam@6
|
298 bmem = BIO_new(BIO_s_mem());
|
adam@7
|
299 BIO_push(b64, bmem);
|
adam@6
|
300 BIO_write(b64, input, length);
|
adam@6
|
301 (void)BIO_flush(b64);
|
adam@6
|
302
|
adam@7
|
303 int len = BIO_ctrl_pending(bmem);
|
adam@7
|
304 char *buff = uw_malloc(ctx, len+1);
|
adam@7
|
305 BIO_read(bmem, buff, len);
|
adam@7
|
306 buff[len] = 0;
|
adam@6
|
307
|
adam@6
|
308 BIO_free_all(b64);
|
adam@6
|
309
|
adam@6
|
310 return buff;
|
adam@6
|
311 }
|
adam@6
|
312
|
adam@8
|
313 static int unbase64(unsigned char *input, int length, unsigned char *buffer, int bufferLength)
|
adam@7
|
314 {
|
adam@7
|
315 BIO *b64, *bmem;
|
adam@8
|
316 int n;
|
adam@6
|
317
|
adam@7
|
318 b64 = BIO_new(BIO_f_base64());
|
adam@7
|
319 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
adam@7
|
320 bmem = BIO_new_mem_buf(input, length);
|
adam@7
|
321 BIO_push(b64, bmem);
|
adam@8
|
322 n = BIO_read(b64, buffer, bufferLength);
|
adam@6
|
323
|
adam@7
|
324 BIO_free_all(bmem);
|
adam@8
|
325
|
adam@8
|
326 return n;
|
adam@8
|
327 }
|
adam@8
|
328
|
adam@12
|
329 uw_Basis_string uw_OpenidFfi_hmac_sha1(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
|
adam@8
|
330 unsigned char keyBin[SHA_DIGEST_LENGTH], out[EVP_MAX_MD_SIZE];
|
adam@8
|
331 unsigned outLen;
|
adam@8
|
332
|
adam@8
|
333 unbase64((unsigned char *)key, strlen(key), keyBin, sizeof keyBin);
|
adam@8
|
334
|
adam@8
|
335 HMAC(EVP_sha1(), keyBin, sizeof keyBin, (unsigned char *)data, strlen(data), out, &outLen);
|
adam@8
|
336 return base64(ctx, out, outLen);
|
adam@6
|
337 }
|
adam@7
|
338
|
adam@12
|
339 uw_Basis_string uw_OpenidFfi_hmac_sha256(uw_context ctx, uw_Basis_string key, uw_Basis_string data) {
|
adam@7
|
340 unsigned char keyBin[SHA256_DIGEST_LENGTH], out[EVP_MAX_MD_SIZE];
|
adam@7
|
341 unsigned outLen;
|
adam@7
|
342
|
adam@7
|
343 unbase64((unsigned char *)key, strlen(key), keyBin, sizeof keyBin);
|
adam@7
|
344
|
adam@7
|
345 HMAC(EVP_sha256(), keyBin, sizeof keyBin, (unsigned char *)data, strlen(data), out, &outLen);
|
adam@7
|
346 return base64(ctx, out, outLen);
|
adam@7
|
347 }
|
adam@8
|
348
|
adam@8
|
349 static uw_Basis_string btwoc(uw_context ctx, const BIGNUM *n) {
|
adam@8
|
350 int len = BN_num_bytes(n), i;
|
adam@8
|
351 unsigned char bytes[len+1];
|
adam@8
|
352
|
adam@8
|
353 bytes[0] = 0;
|
adam@8
|
354 BN_bn2bin(n, bytes+1);
|
adam@8
|
355
|
adam@8
|
356 for (i = 1; i <= len; ++i)
|
adam@8
|
357 if (bytes[i]) {
|
adam@8
|
358 if (bytes[i] & 0x80)
|
adam@8
|
359 --i;
|
adam@8
|
360 break;
|
adam@8
|
361 }
|
adam@8
|
362
|
adam@8
|
363 if (i > len)
|
adam@8
|
364 i = len;
|
adam@8
|
365
|
adam@8
|
366 return base64(ctx, bytes+i, len+1-i);
|
adam@8
|
367 }
|
adam@8
|
368
|
adam@8
|
369 static BIGNUM *unbtwoc(uw_context ctx, uw_Basis_string s) {
|
adam@8
|
370 unsigned char bytes[1024];
|
adam@8
|
371 int len;
|
adam@8
|
372
|
adam@8
|
373 len = unbase64((unsigned char *)s, strlen(s), bytes, sizeof bytes);
|
adam@8
|
374 return BN_bin2bn(bytes, len, NULL);
|
adam@8
|
375 }
|
adam@8
|
376
|
adam@8
|
377 uw_Basis_string uw_OpenidFfi_modulus(uw_context ctx, uw_OpenidFfi_dh dh) {
|
adam@8
|
378 return btwoc(ctx, dh->p);
|
adam@8
|
379 }
|
adam@8
|
380
|
adam@8
|
381 uw_Basis_string uw_OpenidFfi_generator(uw_context ctx, uw_OpenidFfi_dh dh) {
|
adam@8
|
382 return btwoc(ctx, dh->g);
|
adam@8
|
383 }
|
adam@8
|
384
|
adam@8
|
385 uw_Basis_string uw_OpenidFfi_public(uw_context ctx, uw_OpenidFfi_dh dh) {
|
adam@8
|
386 return btwoc(ctx, dh->pub_key);
|
adam@8
|
387 }
|
adam@8
|
388
|
adam@8
|
389 static void free_DH(void *data, int will_retry) {
|
adam@8
|
390 DH *dh = data;
|
adam@8
|
391 DH_free(dh);
|
adam@8
|
392 }
|
adam@8
|
393
|
adam@8
|
394 uw_OpenidFfi_dh uw_OpenidFfi_generate(uw_context ctx) {
|
adam@8
|
395 DH *dh = DH_new();
|
adam@8
|
396
|
adam@8
|
397 uw_register_transactional(ctx, dh, NULL, NULL, free_DH);
|
adam@8
|
398
|
adam@8
|
399 DH_generate_parameters_ex(dh, PRIME_LEN, GENERATOR, NULL);
|
adam@8
|
400
|
adam@8
|
401 if (DH_generate_key(dh) != 1)
|
adam@8
|
402 uw_error(ctx, FATAL, "Diffie-Hellman key generation failed");
|
adam@8
|
403
|
adam@8
|
404 return dh;
|
adam@8
|
405 }
|
adam@8
|
406
|
adam@8
|
407 uw_Basis_string uw_OpenidFfi_compute(uw_context ctx, uw_OpenidFfi_dh dh, uw_Basis_string server_pub) {
|
adam@8
|
408 BIGNUM *bn = unbtwoc(ctx, server_pub);
|
adam@12
|
409 unsigned char secret[DH_size(dh)+1], *secretP;
|
adam@8
|
410 int size;
|
adam@8
|
411
|
adam@8
|
412 uw_push_cleanup(ctx, (void (*)(void *))BN_free, bn);
|
adam@8
|
413
|
adam@12
|
414 size = DH_compute_key(secret+1, bn, dh);
|
adam@8
|
415 if (size == -1)
|
adam@8
|
416 uw_error(ctx, FATAL, "Diffie-Hellman key computation failed");
|
adam@8
|
417
|
adam@8
|
418 uw_pop_cleanup(ctx);
|
adam@8
|
419
|
adam@12
|
420 if (size > 0 && (secret[1] & 0x80)) {
|
adam@12
|
421 secret[0] = 0;
|
adam@12
|
422 secretP = secret;
|
adam@12
|
423 ++size;
|
adam@12
|
424 } else
|
adam@12
|
425 secretP = secret+1;
|
adam@12
|
426
|
adam@12
|
427 return base64(ctx, secretP, size);
|
adam@8
|
428 }
|
adam@12
|
429
|
adam@12
|
430 uw_Basis_string uw_OpenidFfi_sha1(uw_context ctx, uw_Basis_string data) {
|
adam@12
|
431 unsigned char dataBin[128], out[EVP_MAX_MD_SIZE];
|
adam@12
|
432 int len;
|
adam@12
|
433
|
adam@12
|
434 len = unbase64((unsigned char *)data, strlen(data), dataBin, sizeof dataBin);
|
adam@12
|
435
|
adam@12
|
436 SHA1(dataBin, len, out);
|
adam@12
|
437 return base64(ctx, out, SHA_DIGEST_LENGTH);
|
adam@12
|
438 }
|
adam@12
|
439
|
adam@12
|
440 uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string data) {
|
adam@12
|
441 unsigned char dataBin[128], out[EVP_MAX_MD_SIZE];
|
adam@12
|
442 int len;
|
adam@12
|
443
|
adam@12
|
444 len = unbase64((unsigned char *)data, strlen(data), dataBin, sizeof dataBin);
|
adam@12
|
445
|
adam@12
|
446 SHA256(dataBin, len, out);
|
adam@12
|
447 return base64(ctx, out, SHA256_DIGEST_LENGTH);
|
adam@12
|
448 }
|
adam@12
|
449
|
adam@12
|
450 uw_Basis_string uw_OpenidFfi_xor(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
|
adam@12
|
451 unsigned char buf1[128], buf2[128], bufO[128];
|
adam@12
|
452 int len1, len2, i;
|
adam@12
|
453
|
adam@12
|
454 len1 = unbase64((unsigned char *)s1, strlen(s1), buf1, sizeof buf1);
|
adam@12
|
455 len2 = unbase64((unsigned char *)s2, strlen(s2), buf2, sizeof buf2);
|
adam@12
|
456
|
adam@12
|
457 for (i = 0; i < len1; ++i)
|
adam@12
|
458 bufO[i] = buf1[i] ^ buf2[i % len2];
|
adam@12
|
459
|
adam@12
|
460 return base64(ctx, bufO, len1);
|
adam@12
|
461 }
|
adam@13
|
462
|
adam@13
|
463 uw_OpenidFfi_inputs uw_OpenidFfi_remode(uw_context ctx, uw_OpenidFfi_outputs out, uw_Basis_string mode) {
|
adam@13
|
464 uw_OpenidFfi_inputs in = uw_OpenidFfi_createInputs(ctx);
|
adam@13
|
465 char *s;
|
adam@13
|
466
|
adam@13
|
467 for (s = out->start; *s; s = strchr(strchr(s, 0)+1, 0)+1)
|
adam@13
|
468 if (!strcmp("openid.mode", s))
|
adam@13
|
469 uw_OpenidFfi_addInput(ctx, in, "openid.mode", mode);
|
adam@13
|
470 else
|
adam@13
|
471 uw_OpenidFfi_addInput(ctx, in, s, strchr(s, 0)+1);
|
adam@13
|
472
|
adam@13
|
473 return in;
|
adam@13
|
474 }
|