Browse Source

Support new 12-byte IV format and legacy 16-byte IV format

Travis Burtrum 1 year ago
parent
commit
7ce7d25ada
2 changed files with 26 additions and 13 deletions
  1. 3
    1
      README.md
  2. 23
    12
      aesgcm.c

+ 3
- 1
README.md View File

@@ -1,7 +1,9 @@
1 1
 # ImageDownloader
2 2
 When [Conversations](https://conversations.im) uploads an encrypted image with [XEP-0363: HTTP Upload](http://xmpp.org/extensions/xep-0363.html) it appends the encryption key as an anchor to the URL.
3 3
 
4
-The anchor is made of 96 characters which represent 48 bytes in HEX. The first 16 bytes are the IV the last 32 bytes are the key.
4
+There are now [2 formats for anchors](https://github.com/siacs/Conversations/issues/2578).  
5
+*LEGACY FORMAT*:  The anchor is made of 96 characters which represent 48 bytes in HEX. The first 16 bytes are the IV the last 32 bytes are the key.  
6
+*CURRENT FORMAT*: The anchor is made of 88 characters which represent 44 bytes in HEX. The first 12 bytes are the IV the last 32 bytes are the key.  
5 7
 
6 8
 The encryption mode is ```aes-256-gcm```. The authentication tag of 16 bytes is appended to the file.
7 9
 

+ 23
- 12
aesgcm.c View File

@@ -3,13 +3,14 @@
3 3
 #include <unistd.h>
4 4
 #include <openssl/evp.h>
5 5
 
6
-#define TAG_IV_LENGTH 16
6
+#define TAG_LENGTH 16
7 7
 #define BYTES_PER_READ 32 * 1024 // 32kb
8 8
 #define INITIAL_BUFFER_SIZE 256 * 1024 // 256kb, must be at least 2*BYTES_PER_READ
9 9
 
10
-void hex2string(char *src, unsigned char **dst_p)
10
+unsigned int hex2string(char *src, unsigned char **dst_p)
11 11
 {
12
-    *dst_p = malloc(strlen(src)/2);
12
+    unsigned int byte_length = strlen(src)/2;
13
+    *dst_p = malloc(byte_length);
13 14
     unsigned char *dst = *dst_p;
14 15
     unsigned char *end = dst + (strlen(src)/2);
15 16
     unsigned int u;
@@ -18,6 +19,7 @@ void hex2string(char *src, unsigned char **dst_p)
18 19
         *dst++ = u;
19 20
         src += 2;
20 21
     }
22
+    return byte_length;
21 23
 }
22 24
 
23 25
 int main(int argc, char **argv)
@@ -35,7 +37,16 @@ int main(int argc, char **argv)
35 37
     if (argc > 2 && strcmp("enc", argv[2]) == 0)
36 38
         decrypt = 0;
37 39
 
38
-    hex2string(argv[1], &gcm_ivkey);
40
+    unsigned int byte_length = hex2string(argv[1], &gcm_ivkey);
41
+    unsigned int iv_length;
42
+    if(byte_length == 48) {
43
+        iv_length = 16;
44
+    } else if(byte_length == 44) {
45
+        iv_length = 12;
46
+    } else {
47
+        fprintf(stderr, "Invalid key length %d only 44 or 48 bytes supported\n", byte_length);
48
+        return 1;
49
+    }
39 50
 
40 51
     gcm_ct = malloc(total_size);
41 52
 
@@ -53,9 +64,9 @@ int main(int argc, char **argv)
53 64
     }
54 65
 
55 66
     if(decrypt)
56
-        actual_size -= TAG_IV_LENGTH;
67
+        actual_size -= TAG_LENGTH;
57 68
 
58
-    gcm_pt = malloc(decrypt ? actual_size : (actual_size + TAG_IV_LENGTH));
69
+    gcm_pt = malloc(decrypt ? actual_size : (actual_size + TAG_LENGTH));
59 70
 
60 71
     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
61 72
 
@@ -66,14 +77,14 @@ int main(int argc, char **argv)
66 77
         EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
67 78
 
68 79
     /* Set IV length, omit for 96 bits */
69
-    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, TAG_IV_LENGTH, NULL);
80
+    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length, NULL);
70 81
 
71 82
     if(decrypt) {
72 83
         /* Specify key and IV */
73
-        EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey + TAG_IV_LENGTH, gcm_ivkey);
84
+        EVP_DecryptInit_ex(ctx, NULL, NULL, gcm_ivkey + iv_length, gcm_ivkey);
74 85
 
75 86
         /* Set expected tag value. */
76
-        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_IV_LENGTH, gcm_ct + actual_size);
87
+        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAG_LENGTH, gcm_ct + actual_size);
77 88
 
78 89
         /* Decrypt plaintext */
79 90
         EVP_DecryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
@@ -82,7 +93,7 @@ int main(int argc, char **argv)
82 93
         rv = EVP_DecryptFinal_ex(ctx, gcm_pt, &final_outlen);
83 94
     } else {
84 95
         /* Specify key and IV */
85
-        EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_ivkey + TAG_IV_LENGTH, gcm_ivkey);
96
+        EVP_EncryptInit_ex(ctx, NULL, NULL, gcm_ivkey + iv_length, gcm_ivkey);
86 97
 
87 98
         /* Encrypt plaintext */
88 99
         EVP_EncryptUpdate(ctx, gcm_pt, &outlen, gcm_ct, actual_size);
@@ -91,7 +102,7 @@ int main(int argc, char **argv)
91 102
         rv = EVP_EncryptFinal_ex(ctx, gcm_pt, &final_outlen);
92 103
 
93 104
         /* Get expected tag value. */
94
-        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_IV_LENGTH, gcm_pt + actual_size);
105
+        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_LENGTH, gcm_pt + actual_size);
95 106
     }
96 107
 
97 108
     EVP_CIPHER_CTX_free(ctx);
@@ -100,7 +111,7 @@ int main(int argc, char **argv)
100 111
 
101 112
     if (rv > 0) {
102 113
         // success!
103
-        fwrite(gcm_pt, 1, decrypt ? outlen : (outlen + TAG_IV_LENGTH), stdout);
114
+        fwrite(gcm_pt, 1, decrypt ? outlen : (outlen + TAG_LENGTH), stdout);
104 115
         free(gcm_pt);
105 116
         return 0;
106 117
     } else {

Loading…
Cancel
Save