annotate connectors/core.c @ 280:49e9e591c9bb

Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
author MrJuneJune <me@mrjunejune.com>
date Tue, 18 Aug 2026 19:14:53 -0700
parents b3b547563ec7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 #include "connectors/connector.h"
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 #include <openssl/evp.h>
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 #include <openssl/rand.h>
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 #include <stdio.h>
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 #include <string.h>
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 static const char BASE64URL[] =
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 boolean Connector_Base64Url_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 const uint8 *input, size_t input_length, char *output, size_t output_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 size_t required = (input_length * 4 + 2) / 3;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 if (!input || !output || output_size <= required)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 size_t i = 0, j = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 while (i + 3 <= input_length) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 uint32 value = ((uint32)input[i] << 16) |
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 ((uint32)input[i + 1] << 8) | input[i + 2];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 output[j++] = BASE64URL[(value >> 18) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 output[j++] = BASE64URL[(value >> 12) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 output[j++] = BASE64URL[(value >> 6) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 output[j++] = BASE64URL[value & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 i += 3;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 if (i < input_length) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 uint32 value = (uint32)input[i] << 16;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 output[j++] = BASE64URL[(value >> 18) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 if (i + 1 < input_length) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 value |= (uint32)input[i + 1] << 8;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 output[j++] = BASE64URL[(value >> 12) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 output[j++] = BASE64URL[(value >> 6) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 } else {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 output[j++] = BASE64URL[(value >> 12) & 63];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 output[j] = '\0';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 return TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 static int32 base64url_value(char c)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 const char *position = strchr(BASE64URL, c);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 return position ? (int32)(position - BASE64URL) : -1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 boolean Connector_Base64Url_Decode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 const char *input, uint8 *output, size_t output_size, size_t *output_length)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 if (!input || !output || !output_length)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 size_t length = strlen(input);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 if ((length % 4) == 1 || output_size < (length * 3) / 4)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 uint32 accumulator = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 int32 bits = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 size_t written = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 for (size_t i = 0; i < length; ++i) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 int32 value = base64url_value(input[i]);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 if (value < 0)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 accumulator = (accumulator << 6) | (uint32)value;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 bits += 6;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 if (bits >= 8) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 bits -= 8;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 if (written >= output_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 output[written++] = (uint8)((accumulator >> bits) & 255);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 *output_length = written;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 return TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 boolean Connector_Encrypt(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 const Connector_Master_Key *key, const char *plaintext,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78 char *encoded, size_t encoded_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80 if (!key || !plaintext || !encoded)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 size_t plaintext_length = strlen(plaintext);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83 if (plaintext_length > 4096)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 uint8 nonce[12], tag[16], ciphertext[4096];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86 if (RAND_bytes(nonce, sizeof(nonce)) != 1)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89 int32 length = 0, total = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 boolean ok = context &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 EVP_EncryptInit_ex(context, EVP_aes_256_gcm(), NULL, NULL, NULL) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, sizeof(nonce), NULL) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 EVP_EncryptInit_ex(context, NULL, NULL, key->key, nonce) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 EVP_EncryptUpdate(context, ciphertext, &length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 (const uint8 *)plaintext, (int32)plaintext_length) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 total = length;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 ok = ok && EVP_EncryptFinal_ex(context, ciphertext + total, &length) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 total += length;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 ok = ok && EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 EVP_CIPHER_CTX_free(context);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101 if (!ok)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 uint8 envelope[4 + 12 + 16 + 4096];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 envelope[0] = (uint8)(key->version >> 24);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 envelope[1] = (uint8)(key->version >> 16);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 envelope[2] = (uint8)(key->version >> 8);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 envelope[3] = (uint8)key->version;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 memcpy(envelope + 4, nonce, sizeof(nonce));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 memcpy(envelope + 16, tag, sizeof(tag));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110 memcpy(envelope + 32, ciphertext, (size_t)total);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 return Connector_Base64Url_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112 envelope, 32 + (size_t)total, encoded, encoded_size);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115 boolean Connector_Decrypt(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116 const Connector_Master_Key *key, const char *encoded,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117 char *plaintext, size_t plaintext_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
119 uint8 envelope[4 + 12 + 16 + 4096];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
120 size_t envelope_length = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
121 if (!key || !encoded || !plaintext ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
122 !Connector_Base64Url_Decode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 encoded, envelope, sizeof(envelope), &envelope_length) ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124 envelope_length < 32)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 uint32 version = ((uint32)envelope[0] << 24) |
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
127 ((uint32)envelope[1] << 16) | ((uint32)envelope[2] << 8) | envelope[3];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 size_t ciphertext_length = envelope_length - 32;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129 if (version != key->version || plaintext_size <= ciphertext_length)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 int32 length = 0, total = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 boolean ok = context &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 EVP_DecryptInit_ex(context, EVP_aes_256_gcm(), NULL, NULL, NULL) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
135 EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
136 EVP_DecryptInit_ex(context, NULL, NULL, key->key, envelope + 4) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 EVP_DecryptUpdate(context, (uint8 *)plaintext, &length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138 envelope + 32, (int32)ciphertext_length) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 total = length;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140 ok = ok && EVP_CIPHER_CTX_ctrl(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
141 context, EVP_CTRL_GCM_SET_TAG, 16, envelope + 16) == 1 &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
142 EVP_DecryptFinal_ex(context, (uint8 *)plaintext + total, &length) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
143 total += length;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144 EVP_CIPHER_CTX_free(context);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145 if (!ok) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146 memset(plaintext, 0, plaintext_size);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 plaintext[total] = '\0';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 return TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
152
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
153 boolean Connector_Form_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
154 const char *input, char *output, size_t output_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
155 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
156 static const char hex[] = "0123456789ABCDEF";
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
157 if (!input || !output)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
158 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
159 size_t j = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
160 for (size_t i = 0; input[i]; ++i) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
161 uint8 c = (uint8)input[i];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
162 boolean safe = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
163 (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
164 size_t needed = safe ? 1 : 3;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
165 if (j + needed >= output_size)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
166 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
167 if (safe)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
168 output[j++] = (char)c;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
169 else {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
170 output[j++] = '%';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
171 output[j++] = hex[c >> 4];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
172 output[j++] = hex[c & 15];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
173 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
174 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
175 output[j] = '\0';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
176 return TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
177 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
178
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
179 const char *Connector_Operation_Name(Connector_Operation operation)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181 static const char *names[] = {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
182 "drive.list", "drive.get", "drive.download", "drive.changes",
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
183 "drive.create", "drive.upload", "drive.update", "gmail.list",
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
184 "gmail.get", "gmail.attachment", "gmail.history", "gmail.draft.create",
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
185 "gmail.send"
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 };
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 return operation >= CONNECTOR_OP_DRIVE_LIST &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
188 operation <= CONNECTOR_OP_GMAIL_SEND ? names[operation] : "unknown";
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
189 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
190
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
191 boolean Connector_Operation_Is_Mutation(Connector_Operation operation)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
192 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
193 return operation == CONNECTOR_OP_DRIVE_CREATE ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
194 operation == CONNECTOR_OP_DRIVE_UPLOAD ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
195 operation == CONNECTOR_OP_DRIVE_UPDATE ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
196 operation == CONNECTOR_OP_GMAIL_DRAFT_CREATE ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
197 operation == CONNECTOR_OP_GMAIL_SEND;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
198 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
199
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
200 boolean Connector_Operation_Is_Allowed(Connector_Operation operation)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
201 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 return operation >= CONNECTOR_OP_DRIVE_LIST &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 operation <= CONNECTOR_OP_GMAIL_SEND;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
205
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
206 boolean Connector_Request_Digest(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
207 const char *user_id, const char *account_id, Connector_Operation operation,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
208 const Connector_Provider_Request *request, char output[65])
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
209 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
210 if (!user_id || !account_id || !request || !output ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 request->body_length > CONNECTOR_MAX_JSON_BYTES)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 EVP_MD_CTX *context = EVP_MD_CTX_new();
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 uint8 digest[32];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215 uint32 digest_length = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216 const char separator = '\0';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 #define HASH_FIELD(value, length) do { \
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 EVP_DigestUpdate(context, (value) ? (value) : "", (value) ? (length) : 0); \
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 EVP_DigestUpdate(context, &separator, 1); \
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 } while (0)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221 boolean ok = context &&
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 EVP_DigestInit_ex(context, EVP_sha256(), NULL) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 if (!ok) {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224 EVP_MD_CTX_free(context);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227 const char *name = Connector_Operation_Name(operation);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 HASH_FIELD(user_id, strlen(user_id));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229 HASH_FIELD(account_id, strlen(account_id));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 HASH_FIELD(name, strlen(name));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231 HASH_FIELD(request->method, request->method ? strlen(request->method) : 0);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 HASH_FIELD(request->path, request->path ? strlen(request->path) : 0);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
233 HASH_FIELD(request->query, request->query ? strlen(request->query) : 0);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
234 HASH_FIELD(request->content_type,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
235 request->content_type ? strlen(request->content_type) : 0);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
236 HASH_FIELD(request->body, request->body_length);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 uint8 overwrite = request->overwrite ? 1 : 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238 EVP_DigestUpdate(context, &overwrite, 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 ok = EVP_DigestFinal_ex(context, digest, &digest_length) == 1;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240 EVP_MD_CTX_free(context);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241 #undef HASH_FIELD
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 if (!ok || digest_length != 32)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 for (size_t i = 0; i < sizeof(digest); ++i)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
245 snprintf(output + i * 2, 3, "%02x", digest[i]);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246 output[64] = '\0';
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247 return TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 }
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
250 boolean Connector_OAuth_PKCE_Start(Connector_OAuth_Start *start)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
251 {
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
252 uint8 state[32], verifier[48], digest[32];
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
253 uint32 digest_length = 0;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
254 if (!start || RAND_bytes(state, sizeof(state)) != 1 ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
255 RAND_bytes(verifier, sizeof(verifier)) != 1 ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
256 !Connector_Base64Url_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
257 state, sizeof(state), start->state, sizeof(start->state)) ||
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
258 !Connector_Base64Url_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
259 verifier, sizeof(verifier), start->code_verifier,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
260 sizeof(start->code_verifier)))
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
261 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
262 if (EVP_Digest(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
263 start->code_verifier, strlen(start->code_verifier), digest,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
264 &digest_length, EVP_sha256(), NULL) != 1 || digest_length != 32)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
265 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
266 return Connector_Base64Url_Encode(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
267 digest, sizeof(digest), start->code_challenge,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
268 sizeof(start->code_challenge));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
269 }