︙ | | |
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
-
+
+
|
*
*-------------------------------------------------------------------
*/
int EncryptInitialize(Tcl_Interp *interp, int type, EVP_CIPHER_CTX **ctx,
Tcl_Obj *cipherObj, Tcl_Obj *keyObj, Tcl_Obj *ivObj) {
const EVP_CIPHER *cipher;
char *keyString = NULL, *ivString = NULL;
int cipher_len = 0, key_len = 0, iv_len = 0, res, max;
Tcl_Size key_len = 0, iv_len = 0;
int res, max;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
dprintf("Called");
/* Init buffers */
memset(key, 0, EVP_MAX_KEY_LENGTH);
memset(iv, 0, EVP_MAX_IV_LENGTH);
|
︙ | | |
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
-
+
|
if (type == TYPE_ENCRYPT) {
res = EVP_EncryptInit_ex(*ctx, cipher, NULL, key, iv);
} else {
res = EVP_DecryptInit_ex(*ctx, cipher, NULL, key, iv);
}
if(!res) {
Tcl_AppendResult(interp, "Initialize failed: ", REASON(), NULL);
Tcl_AppendResult(interp, "Initialize failed: ", REASON(), (char *) NULL);
return TCL_ERROR;
}
/* Erase buffers */
memset(key, 0, EVP_MAX_KEY_LENGTH);
memset(iv, 0, EVP_MAX_IV_LENGTH);
return TCL_OK;
|
︙ | | |
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
-
+
-
+
-
+
-
+
|
*
* Side effects:
* Adds encrypted data to buffer or sets result to error message
*
*-------------------------------------------------------------------
*/
int EncryptUpdate(Tcl_Interp *interp, int type, EVP_CIPHER_CTX *ctx, unsigned char *out_buf,
int *out_len, unsigned char *data, int data_len) {
int *out_len, unsigned char *data, Tcl_Size data_len) {
int res;
dprintf("Called");
/* Encrypt/decrypt data */
if (type == TYPE_ENCRYPT) {
res = EVP_EncryptUpdate(ctx, out_buf, out_len, data, data_len);
res = EVP_EncryptUpdate(ctx, out_buf, out_len, data, (int) data_len);
} else {
res = EVP_DecryptUpdate(ctx, out_buf, out_len, data, data_len);
res = EVP_DecryptUpdate(ctx, out_buf, out_len, data, (int) data_len);
}
if (res) {
return TCL_OK;
} else {
Tcl_AppendResult(interp, "Update failed: ", REASON(), NULL);
Tcl_AppendResult(interp, "Update failed: ", REASON(), (char *) NULL);
return TCL_ERROR;
}
}
/*
*-------------------------------------------------------------------
*
|
︙ | | |
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
-
+
|
} else {
res = EVP_DecryptFinal_ex(ctx, out_buf, out_len);
}
if (res) {
return TCL_OK;
} else {
Tcl_AppendResult(interp, "Finalize failed: ", REASON(), NULL);
Tcl_AppendResult(interp, "Finalize failed: ", REASON(), (char *) NULL);
return TCL_ERROR;
}
}
/*******************************************************************/
/*
|
︙ | | |
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
|
-
+
|
Tcl_Channel parent = Tcl_GetStackedChannel(statePtr->self);
int out_len;
unsigned char out_buf[EVP_MAX_BLOCK_LENGTH];
/* Finalize function */
if (EncryptFinalize(interp, statePtr->type, statePtr->ctx, out_buf, &out_len) == TCL_OK) {
if (out_len > 0) {
int len = Tcl_WriteRaw(parent, (const char *) out_buf, out_len);
Tcl_Size len = Tcl_WriteRaw(parent, (const char *) out_buf, (Tcl_Size) out_len);
if (len < 0) {
return Tcl_GetErrno();
}
}
} else {
/* Error */
}
|
︙ | | |
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
|
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
-
+
+
-
+
-
+
-
+
-
+
-
+
|
* Read data from transform and write to buf
*
*----------------------------------------------------------------------
*/
int EncryptInputProc(ClientData clientData, char *buf, int toRead, int *errorCodePtr) {
EncryptState *statePtr = (EncryptState *) clientData;
Tcl_Channel parent;
int read, out_len;
int out_len;
Tcl_Size read;
*errorCodePtr = 0;
char *in_buf;
/* Abort if nothing to process */
if (toRead <= 0 || statePtr->self == (Tcl_Channel) NULL) {
return 0;
}
/* Get bytes from underlying channel */
in_buf = Tcl_Alloc(toRead);
in_buf = Tcl_Alloc((Tcl_Size) toRead);
parent = Tcl_GetStackedChannel(statePtr->self);
read = Tcl_ReadRaw(parent, in_buf, toRead);
read = Tcl_ReadRaw(parent, in_buf, (Tcl_Size) toRead);
/* Update function */
if (read > 0) {
/* Have data - Update function */
if (EncryptUpdate(statePtr->interp, statePtr->type, statePtr->ctx, buf, &out_len, in_buf, read) == TCL_OK) {
/* If have data, put in buf, otherwise tell TCL to try again */
if (out_len > 0) {
read = out_len;
read = (Tcl_Size) out_len;
} else {
*errorCodePtr = EAGAIN;
read = -1;
}
} else {
Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Update failed: %s", REASON()));
*errorCodePtr = EINVAL;
read = 0;
}
} else if (read < 0) {
/* Error */
*errorCodePtr = Tcl_GetErrno();
} else if (!(statePtr->flags & CHAN_EOF)) {
/* EOF - Finalize function and put any remaining data in buf */
if (EncryptFinalize(statePtr->interp, statePtr->type, statePtr->ctx, buf, &out_len) == TCL_OK) {
read = out_len;
read = (Tcl_Size) out_len;
} else {
Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Finalize failed: %s", REASON()));
*errorCodePtr = EINVAL;
read = 0;
}
statePtr->flags |= CHAN_EOF;
}
Tcl_Free(in_buf);
return read;
return (int) read;
}
/*
*----------------------------------------------------------------------
*
* EncryptOutputProc --
*
|
︙ | | |
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
|
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
|
-
+
-
+
-
+
|
char *out_buf;
/* Abort if nothing to process */
if (toWrite <= 0 || statePtr->self == (Tcl_Channel) NULL) {
return 0;
}
out_buf = Tcl_Alloc(toWrite+EVP_MAX_BLOCK_LENGTH);
out_buf = Tcl_Alloc((Tcl_Size) toWrite+EVP_MAX_BLOCK_LENGTH);
/* Update function */
if (EncryptUpdate(statePtr->interp, statePtr->type, statePtr->ctx, out_buf, &out_len, buf, toWrite) == TCL_OK) {
if (EncryptUpdate(statePtr->interp, statePtr->type, statePtr->ctx, out_buf, &out_len, buf, (Tcl_Size) toWrite) == TCL_OK) {
/* If have data, output it, otherwise tell TCL to try again */
if (out_len > 0) {
Tcl_Channel parent = Tcl_GetStackedChannel(statePtr->self);
write = Tcl_WriteRaw(parent, (const char *) out_buf, out_len);
write = (int) Tcl_WriteRaw(parent, (const char *) out_buf, (Tcl_Size) out_len);
write = toWrite;
} else {
*errorCodePtr = EAGAIN;
write = -1;
}
} else {
|
︙ | | |
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
|
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
|
-
+
|
/* Validate arg count */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
/* Get channel */
chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), &mode);
chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], (Tcl_Size *) NULL), &mode);
if (chan == (Tcl_Channel) NULL) {
return TCL_ERROR;
}
/* Make sure to operate on the topmost channel */
chan = Tcl_GetTopChannel(chan);
|
︙ | | |
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
|
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
|
+
-
+
|
* Side effects:
* Adds data to encrypt/decrypt function
*
*-------------------------------------------------------------------
*/
int EncryptInstanceObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
EncryptState *statePtr = (EncryptState *) clientData;
int fn, out_len;
int fn, data_len = 0, out_len;
Tcl_Size data_len = 0;
char *data = NULL;
Tcl_Obj *resultObj;
unsigned char *out_buf;
static const char *instance_fns [] = { "finalize", "update", NULL };
dprintf("Called");
|
︙ | | |
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
|
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
|
-
+
-
+
|
Tcl_WrongNumArgs(interp, 1, objv, "update data");
Tcl_DecrRefCount(resultObj);
return TCL_ERROR;
}
/* Update function */
if (EncryptUpdate(interp, statePtr->type, statePtr->ctx, out_buf, &out_len, data, data_len) == TCL_OK) {
out_buf = Tcl_SetByteArrayLength(resultObj, out_len);
out_buf = Tcl_SetByteArrayLength(resultObj, (Tcl_Size) out_len);
Tcl_SetObjResult(interp, resultObj);
} else {
Tcl_DecrRefCount(resultObj);
return TCL_ERROR;
}
} else {
/* Finalize function */
if (EncryptFinalize(interp, statePtr->type, statePtr->ctx, out_buf, &out_len) == TCL_OK) {
out_buf = Tcl_SetByteArrayLength(resultObj, out_len);
out_buf = Tcl_SetByteArrayLength(resultObj, (Tcl_Size) out_len);
Tcl_SetObjResult(interp, resultObj);
} else {
Tcl_DecrRefCount(resultObj);
return TCL_ERROR;
}
/* Clean-up */
|
︙ | | |
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
|
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
|
-
+
|
* Creates command or error message
*
*-------------------------------------------------------------------
*/
int EncryptCommandHandler(Tcl_Interp *interp, int type, Tcl_Obj *cmdObj,
Tcl_Obj *cipherObj, Tcl_Obj *digestObj, Tcl_Obj *keyObj, Tcl_Obj *ivObj) {
EncryptState *statePtr;
char *cmdName = Tcl_GetStringFromObj(cmdObj, NULL);
char *cmdName = Tcl_GetStringFromObj(cmdObj, (Tcl_Size *) NULL);
(void *) digestObj;
dprintf("Called");
if ((statePtr = EncryptStateNew(interp, type)) == NULL) {
Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
return TCL_ERROR;
|
︙ | | |
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
|
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
|
-
+
+
-
+
|
* Sets result or error message
*
*-------------------------------------------------------------------
*/
int EncryptDataHandler(Tcl_Interp *interp, int type, Tcl_Obj *dataObj, Tcl_Obj *cipherObj,
Tcl_Obj *digestObj, Tcl_Obj *keyObj, Tcl_Obj *ivObj) {
EVP_CIPHER_CTX *ctx = NULL;
int data_len = 0, out_len = 0, len = 0, res = TCL_OK;
int out_len = 0, len = 0, res = TCL_OK;
Tcl_Size data_len = 0;
unsigned char *data, *out_buf;
Tcl_Obj *resultObj;
(void *) digestObj;
dprintf("Called");
/* Get data */
if (dataObj != NULL) {
data = Tcl_GetByteArrayFromObj(dataObj, &data_len);
} else {
Tcl_AppendResult(interp, "No data", NULL);
Tcl_AppendResult(interp, "No data", (char *) NULL);
return TCL_ERROR;
}
/* Allocate storage for result. Size should be data size + block size. */
resultObj = Tcl_NewObj();
out_buf = Tcl_SetByteArrayLength(resultObj, data_len+EVP_MAX_BLOCK_LENGTH);
if (resultObj == NULL || out_buf == NULL) {
|
︙ | | |
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
|
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
|
-
+
|
goto done;
}
out_len += len;
done:
/* Set output result */
if (res == TCL_OK) {
out_buf = Tcl_SetByteArrayLength(resultObj, out_len);
out_buf = Tcl_SetByteArrayLength(resultObj, (Tcl_Size) out_len);
Tcl_SetObjResult(interp, resultObj);
} else {
Tcl_DecrRefCount(resultObj);
/* Result is error message */
}
/* Clean up */
|
︙ | | |
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
|
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
|
-
+
-
+
|
/* Initialize operation */
if ((res = EncryptInitialize(interp, type, &ctx, cipherObj, keyObj, ivObj)) != TCL_OK) {
goto done;
}
/* Read file data from inFile, encrypt/decrypt it, then output to outFile */
while (!Tcl_Eof(in)) {
int read = Tcl_ReadRaw(in, (char *) in_buf, BUFFER_SIZE);
Tcl_Size read = Tcl_ReadRaw(in, (char *) in_buf, BUFFER_SIZE);
if (read > 0) {
if ((res = EncryptUpdate(interp, type, ctx, out_buf, &out_len, in_buf, read)) == TCL_OK) {
if (out_len > 0) {
len = Tcl_WriteRaw(out, (const char *) out_buf, out_len);
len = (int) Tcl_WriteRaw(out, (const char *) out_buf, (Tcl_Size) out_len);
if (len >= 0) {
total += len;
} else {
Tcl_AppendResult(interp, "Write error: ", Tcl_ErrnoMsg(Tcl_GetErrno()), (char *) NULL);
res = TCL_ERROR;
goto done;
}
|
︙ | | |
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
|
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
|
-
+
|
goto done;
}
}
/* Finalize data and write any remaining data in block */
if ((res = EncryptFinalize(interp, type, ctx, out_buf, &out_len)) == TCL_OK) {
if (out_len > 0) {
len = Tcl_WriteRaw(out, (const char *) out_buf, out_len);
len = (int) Tcl_WriteRaw(out, (const char *) out_buf, (Tcl_Size) out_len);
if (len >= 0) {
total += len;
} else {
Tcl_AppendResult(interp, "Write error: ", Tcl_ErrnoMsg(Tcl_GetErrno()), (char *) NULL);
res = TCL_ERROR;
goto done;
}
|
︙ | | |
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
|
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
|
-
+
+
-
+
-
+
|
*
*-------------------------------------------------------------------
*/
static int EncryptMain(int type, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_Obj *cipherObj = NULL, *cmdObj = NULL, *dataObj = NULL, *digestObj = NULL;
Tcl_Obj *inFileObj = NULL, *outFileObj = NULL, *keyObj = NULL, *ivObj = NULL, *macObj = NULL;
const char *channel = NULL, *opt;
int res, start = 1, fn;
int res, start = 1;
Tcl_Size fn;
dprintf("Called");
/* Clear interp result */
Tcl_ResetResult(interp);
/* Validate arg count */
if (objc < 3 || objc > 12) {
Tcl_WrongNumArgs(interp, 1, objv, "?-cipher? name ?-digest name? -key key ?-iv string? ?-mac name? [-channel chan | -command cmdName | -infile filename -outfile filename | ?-data? data]");
return TCL_ERROR;
}
/* Special case of first arg is cipher */
opt = Tcl_GetStringFromObj(objv[start], NULL);
opt = Tcl_GetStringFromObj(objv[start], (Tcl_Size *) NULL);
if (opt[0] != '-') {
switch(type) {
case TYPE_ENCRYPT:
case TYPE_DECRYPT:
cipherObj = objv[start++];
break;
}
}
/* Get options */
for (int idx = start; idx < objc; idx++) {
/* Special case for when last arg is data */
if (idx == objc - 1) {
opt = Tcl_GetStringFromObj(objv[idx], NULL);
opt = Tcl_GetStringFromObj(objv[idx], (Tcl_Size *) NULL);
if (opt[0] != '-' && dataObj == NULL) {
dataObj = objv[idx];
break;
}
}
/* Get option */
|
︙ | | |
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
|
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
|
-
+
-
+
-
+
|
macObj = objv[idx];
break;
}
}
/* Check for required options */
if (cipherObj == NULL) {
Tcl_AppendResult(interp, "No cipher", NULL);
Tcl_AppendResult(interp, "No cipher", (char *) NULL);
} else if (keyObj == NULL) {
Tcl_AppendResult(interp, "No key", NULL);
Tcl_AppendResult(interp, "No key", (char *) NULL);
return TCL_ERROR;
}
/* Perform encryption function on file, stacked channel, using instance command, or data blob */
if (inFileObj != NULL && outFileObj != NULL) {
res = EncryptFileHandler(interp, type, inFileObj, outFileObj, cipherObj, digestObj, keyObj, ivObj);
} else if (channel != NULL) {
res = EncryptChannelHandler(interp, type, channel, cipherObj, digestObj, keyObj, ivObj);
} else if (cmdObj != NULL) {
res = EncryptCommandHandler(interp, type, cmdObj, cipherObj, digestObj, keyObj, ivObj);
} else if (dataObj != NULL) {
res = EncryptDataHandler(interp, type, dataObj, cipherObj, digestObj, keyObj, ivObj);
} else {
Tcl_AppendResult(interp, "No operation specified: Use -channel, -command, -data, or -infile option", NULL);
Tcl_AppendResult(interp, "No operation specified: Use -channel, -command, -data, or -infile option", (char *) NULL);
res = TCL_ERROR;
}
return res;
}
/*
*-------------------------------------------------------------------
|
︙ | | |