|
2 | 2 |
|
3 | 3 | #include <stdio.h> |
4 | 4 | #include <string.h> |
| 5 | +#include <openssl/aes.h> |
5 | 6 | #include <openssl/err.h> |
6 | 7 | #include <openssl/evp.h> |
7 | 8 |
|
8 | | -int encryptdata(const unsigned char* input, size_t inputlen, |
9 | | - unsigned char* output, size_t* outputlen, |
10 | | - const unsigned char* key); |
11 | | -int decryptdata(const unsigned char* input, size_t inputlen, |
12 | | - unsigned char* output, size_t* outputlen, |
13 | | - const unsigned char* key); |
14 | | -void cmd_main(void); |
| 9 | +#include "git-compat-util.h" |
| 10 | +#include "hash.h" |
| 11 | + |
| 12 | +void setkey(const unsigned char* k); |
| 13 | +unsigned char* encryptdata(const unsigned char* input, size_t inputlen, |
| 14 | + unsigned char* output, size_t* outputlen); |
| 15 | +unsigned char* decryptdata(const unsigned char* input, size_t inputlen, |
| 16 | + unsigned char* output, size_t* outputlen); |
| 17 | +char* encryptrefname(const char* input, char* output); |
| 18 | +char* decryptrefname(const char* input, char* output); |
| 19 | + |
| 20 | +static unsigned char key[48]; |
| 21 | + |
| 22 | +void setkey(const unsigned char* k) { |
| 23 | + memcpy(key, k, 48); |
| 24 | +} |
15 | 25 |
|
16 | 26 | static void handle_openssl_error(const char *message) { |
17 | 27 | fprintf(stderr, "%s\n", message); |
18 | 28 | ERR_print_errors_fp(stderr); |
19 | 29 | } |
20 | 30 |
|
21 | | -int encryptdata(const unsigned char* input, size_t inputlen, |
22 | | - unsigned char* output, size_t* outputlen, |
23 | | - const unsigned char* key) { |
24 | | - const EVP_CIPHER *cipher_type = EVP_aes_256_cbc(); |
25 | | - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); |
26 | | - int outlen; |
27 | | - if (ctx == NULL) { |
| 31 | +struct cryptobj { |
| 32 | + EVP_CIPHER_CTX *ctx; |
| 33 | + unsigned char *output; |
| 34 | + size_t outlen; |
| 35 | +}; |
| 36 | + |
| 37 | +static struct cryptobj* encrypt_init(unsigned char* output) { |
| 38 | + struct cryptobj* co = malloc(sizeof(struct cryptobj)); |
| 39 | + if (co == NULL) |
| 40 | + return NULL; |
| 41 | + co->ctx = EVP_CIPHER_CTX_new(); |
| 42 | + if (co->ctx == NULL) { |
28 | 43 | handle_openssl_error("EVP_CIPHER_CTX_new failed"); |
29 | | - return -1; |
| 44 | + free(co); |
| 45 | + return NULL; |
30 | 46 | } |
31 | | - if (EVP_EncryptInit_ex(ctx, cipher_type, NULL, key, key+32) != 1) { |
| 47 | + if (EVP_EncryptInit_ex(co->ctx, EVP_aes_256_cbc(), NULL, key, key+32) != 1) { |
32 | 48 | handle_openssl_error("EVP_EncryptInit_ex failed"); |
33 | | - EVP_CIPHER_CTX_free(ctx); |
34 | | - return -1; |
| 49 | + EVP_CIPHER_CTX_free(co->ctx); |
| 50 | + free(co); |
| 51 | + return NULL; |
35 | 52 | } |
36 | | - if (EVP_EncryptUpdate(ctx, output, &outlen, input, inputlen) != 1) { |
| 53 | + co->output = output; |
| 54 | + co->outlen = 0; |
| 55 | + return co; |
| 56 | +} |
| 57 | + |
| 58 | +static struct cryptobj* encrypt_update(struct cryptobj* co, |
| 59 | + const unsigned char* input, size_t inputlen) { |
| 60 | + int outlen; |
| 61 | + if (EVP_EncryptUpdate(co->ctx, co->output + co->outlen, &outlen, input, inputlen) != 1) { |
37 | 62 | handle_openssl_error("EVP_EncryptUpdate failed"); |
38 | | - EVP_CIPHER_CTX_free(ctx); |
39 | | - return -1; |
| 63 | + EVP_CIPHER_CTX_free(co->ctx); |
| 64 | + free(co); |
| 65 | + return NULL; |
40 | 66 | } |
41 | | - *outputlen = outlen; |
42 | | - if (EVP_EncryptFinal_ex(ctx, output + *outputlen, &outlen) != 1) { |
| 67 | + co->outlen += outlen; |
| 68 | + return co; |
| 69 | +} |
| 70 | + |
| 71 | +static unsigned char* encrypt_final(struct cryptobj* co, size_t* outputlen) { |
| 72 | + int outlen; |
| 73 | + unsigned char* out = co->output; |
| 74 | + if (EVP_EncryptFinal_ex(co->ctx, co->output + co->outlen, &outlen) != 1) { |
43 | 75 | handle_openssl_error("EVP_EncryptFinal_ex failed"); |
44 | | - EVP_CIPHER_CTX_free(ctx); |
45 | | - return -1; |
| 76 | + EVP_CIPHER_CTX_free(co->ctx); |
| 77 | + free(co); |
| 78 | + return NULL; |
46 | 79 | } |
47 | | - *outputlen += outlen; |
48 | | - EVP_CIPHER_CTX_free(ctx); |
49 | | - return 0; |
| 80 | + co->outlen += outlen; |
| 81 | + *outputlen = co->outlen; |
| 82 | + EVP_CIPHER_CTX_free(co->ctx); |
| 83 | + free(co); |
| 84 | + return out; |
50 | 85 | } |
51 | 86 |
|
52 | | -int decryptdata(const unsigned char* input, size_t inputlen, |
53 | | - unsigned char* output, size_t* outputlen, |
54 | | - const unsigned char* key) { |
| 87 | +unsigned char* encryptdata(const unsigned char* input, size_t inputlen, |
| 88 | + unsigned char* output, size_t* outputlen) { |
| 89 | + struct cryptobj* co = encrypt_init(output); |
| 90 | + encrypt_update(co, input, inputlen); |
| 91 | + return encrypt_final(co, outputlen); |
| 92 | +} |
| 93 | + |
| 94 | +unsigned char* decryptdata(const unsigned char* input, size_t inputlen, |
| 95 | + unsigned char* output, size_t* outputlen) { |
55 | 96 | const EVP_CIPHER *cipher_type = EVP_aes_256_cbc(); |
56 | 97 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); |
57 | 98 | int outlen; |
58 | 99 | if (ctx == NULL) { |
59 | 100 | handle_openssl_error("EVP_CIPHER_CTX_new failed"); |
60 | | - return -1; |
| 101 | + return NULL; |
61 | 102 | } |
62 | 103 | if (EVP_DecryptInit_ex(ctx, cipher_type, NULL, key, key+32) != 1) { |
63 | 104 | handle_openssl_error("EVP_DecryptInit_ex failed"); |
64 | 105 | EVP_CIPHER_CTX_free(ctx); |
65 | | - return -1; |
| 106 | + return NULL; |
66 | 107 | } |
67 | 108 | if (EVP_DecryptUpdate(ctx, output, &outlen, input, inputlen) != 1) { |
68 | 109 | handle_openssl_error("EVP_DecryptUpdate failed"); |
69 | 110 | EVP_CIPHER_CTX_free(ctx); |
70 | | - return -1; |
| 111 | + return NULL; |
71 | 112 | } |
72 | 113 | *outputlen = outlen; |
73 | 114 | if (EVP_DecryptFinal_ex(ctx, output + *outputlen, &outlen) != 1) { |
74 | 115 | handle_openssl_error("EVP_DecryptFinal_ex failed"); |
75 | 116 | EVP_CIPHER_CTX_free(ctx); |
76 | | - return -1; |
| 117 | + return NULL; |
77 | 118 | } |
78 | 119 | *outputlen += outlen; |
79 | 120 | EVP_CIPHER_CTX_free(ctx); |
80 | | - return 0; |
| 121 | + return output; |
| 122 | +} |
| 123 | + |
| 124 | +static void base64encode(const unsigned char* input, size_t inputlen, |
| 125 | + unsigned char* output, size_t* outputlen) { |
| 126 | + static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+#="; |
| 127 | + size_t r = 0, w = 0; |
| 128 | + while (r < inputlen) { |
| 129 | + unsigned char b[5] = { 0, 0, 0, 0, 0 }; |
| 130 | + int l = r + 3 < inputlen ? 3 : (inputlen - r); |
| 131 | + memcpy(b + 1, input + r, l); |
| 132 | + for (int i = 0; i < 4; ++i) |
| 133 | + output[w + i] = |
| 134 | + b64[(l > i - 1) ? |
| 135 | + ((b[i + 0] << ((3 - i) << 1)) | |
| 136 | + (b[i + 1] >> ((1 + i) << 1))) & 0x3f : |
| 137 | + 64]; |
| 138 | + r += 3; |
| 139 | + w += 4; |
| 140 | + } |
| 141 | + *outputlen = w; |
81 | 142 | } |
82 | 143 |
|
83 | | -void cmd_main(void) { |
| 144 | +static void base64decode(const unsigned char* input, size_t inputlen, |
| 145 | + unsigned char* output, size_t* outputlen) { |
| 146 | + static const unsigned char b64[] = { |
| 147 | + -1, -1, -1, 63, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, -1, |
| 148 | + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 64, -1, -1, |
| 149 | + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 150 | + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, |
| 151 | + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
| 152 | + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, |
| 153 | + }; |
| 154 | + unsigned char b[4] = { 0, 0, 0, 0 }; |
| 155 | + size_t r = 0, w = 0; |
| 156 | + while (r < inputlen) { |
| 157 | + for (int i = 0; i < 4; ++i) |
| 158 | + b[i] = b64[input[r + i] - 32]; |
| 159 | + for (int i = 0; i < 3; ++i) |
| 160 | + output[w + i] = |
| 161 | + (b[i + 0] << ((1 + i) << 1)) | |
| 162 | + (b[i + 1] >> ((2 - i) << 1)); |
| 163 | + r += 4; |
| 164 | + w += 3; |
| 165 | + } |
| 166 | + *outputlen = w - (b[2] >= 64 ? 2 : (b[3] >= 64 ? 1 : 0)); |
| 167 | +} |
| 168 | + |
| 169 | +char* encryptrefname(const char* input, char* output) { |
| 170 | + struct git_hash_ctx c; |
| 171 | + size_t inputlen = strlen(input); |
| 172 | + size_t hashlen = hash_algos[GIT_HASH_SHA1].rawsz; |
| 173 | + unsigned char* buf1 = malloc(hashlen); |
| 174 | + unsigned char* buf2 = malloc(hashlen + inputlen + AES_BLOCK_SIZE); |
| 175 | + size_t buf2len; |
| 176 | + size_t outlen; |
| 177 | + struct cryptobj* co = encrypt_init(buf2); |
| 178 | + hash_algos[GIT_HASH_SHA1].init_fn(&c); |
| 179 | + git_hash_update(&c, input, inputlen); |
| 180 | + git_hash_final(buf1, &c); |
| 181 | + encrypt_update(co, buf1, hashlen); |
| 182 | + encrypt_update(co, (const unsigned char*)input, inputlen); |
| 183 | + encrypt_final(co, &buf2len); |
| 184 | + base64encode(buf2, buf2len, (unsigned char*)output, &outlen); |
| 185 | + output[outlen] = '\0'; |
| 186 | + free(buf1); |
| 187 | + free(buf2); |
| 188 | + return output; |
| 189 | +} |
| 190 | + |
| 191 | +char* decryptrefname(const char* input, char* output) { |
| 192 | + const char* data = strrchr(input, '/'); |
| 193 | + size_t inputlen; |
| 194 | + unsigned char* buf1; |
| 195 | + unsigned char* buf2; |
| 196 | + size_t outlen1; |
| 197 | + size_t outlen2; |
| 198 | + size_t hashlen = hash_algos[GIT_HASH_SHA1].rawsz; |
| 199 | + data = data ? data + 1 : input; |
| 200 | + inputlen = strlen(data); |
| 201 | + buf1 = malloc(inputlen * 3 / 4); |
| 202 | + buf2 = malloc(inputlen * 3 / 4); |
| 203 | + base64decode((const unsigned char*)data, inputlen, buf1, &outlen1); |
| 204 | + decryptdata((const unsigned char*)buf1, outlen1, buf2, &outlen2); |
| 205 | + memcpy(output, buf2 + hashlen, outlen2 - hashlen); |
| 206 | + output[outlen2 - hashlen] = '\0'; |
| 207 | + return output; |
| 208 | +} |
| 209 | + |
| 210 | +int cmd_main(int argc, const char** argv) { |
| 211 | + (void)argv; |
| 212 | + (void)argc; |
| 213 | + (void)base64decode; |
| 214 | + return 0; |
84 | 215 | } |
0 commit comments