Diff
EuroTcl/OpenACS 11 - 12 JULY 2024, VIENNA

Differences From Artifact [9e69cd3c7b]:

To Artifact [03763b15bf]:


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199




200
201
202
203
204
205
206
 * Side effects:
 *	No result or error message
 *
 *-------------------------------------------------------------------
 */
int Tls_DigestInit(Tcl_Interp *interp, DigestState *statePtr, const EVP_MD *md,
	const EVP_CIPHER *cipher, Tcl_Obj *keyObj) {
    int key_len, res = 0;
    const unsigned char *key;

    /* Create message digest context */
    if (statePtr->format & TYPE_MD) {
	statePtr->ctx = EVP_MD_CTX_new();
	res = (statePtr->ctx != NULL);
    } else if (statePtr->format & TYPE_HMAC) {
	statePtr->hctx = HMAC_CTX_new();
	res = (statePtr->hctx != NULL);
    } else if (statePtr->format & TYPE_CMAC) {
	statePtr->cctx = CMAC_CTX_new();
	res = (statePtr->cctx != NULL);
    }
    if (!res) {
	Tcl_AppendResult(interp, "Create digest context failed: ", REASON(), NULL);
	return TCL_ERROR;
    }

    /* Initialize hash function */
    if (statePtr->format & TYPE_MD) {
	res = EVP_DigestInit_ex(statePtr->ctx, md, NULL);
    } else if (statePtr->format & TYPE_HMAC) {
	key = Tcl_GetByteArrayFromObj(keyObj, &key_len);
	res = HMAC_Init_ex(statePtr->hctx, (const void *) key, key_len, md, NULL);
    } else if (statePtr->format & TYPE_CMAC) {
	key = Tcl_GetByteArrayFromObj(keyObj, &key_len);
	res = CMAC_Init(statePtr->cctx, (const void *) key, key_len, cipher, NULL);
    }
    if (!res) {
	Tcl_AppendResult(interp, "Initialize digest failed: ", REASON(), NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------
 *
 * Tls_DigestUpdate --
 *
 *	Update a hash function
 *
 * Returns:
 *	1 if successful or 0 for failure
 *
 * Side effects:
 *	Adds buf to hash function
 *
 *-------------------------------------------------------------------
 */
int Tls_DigestUpdate(DigestState *statePtr, char *buf, size_t read) {
    int res = 0;

    if (statePtr->format & TYPE_MD) {
	res = EVP_DigestUpdate(statePtr->ctx, buf, read);
    } else if (statePtr->format & TYPE_HMAC) {
	res = HMAC_Update(statePtr->hctx, buf, read);
    } else if (statePtr->format & TYPE_CMAC) {
	res = CMAC_Update(statePtr->cctx, buf, read);




    }
    return res;
}

/*
 *-------------------------------------------------------------------
 *







|














|














|




















|








>
>
>
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
 * Side effects:
 *	No result or error message
 *
 *-------------------------------------------------------------------
 */
int Tls_DigestInit(Tcl_Interp *interp, DigestState *statePtr, const EVP_MD *md,
	const EVP_CIPHER *cipher, Tcl_Obj *keyObj) {
    int key_len = 0, res = 0;
    const unsigned char *key;

    /* Create message digest context */
    if (statePtr->format & TYPE_MD) {
	statePtr->ctx = EVP_MD_CTX_new();
	res = (statePtr->ctx != NULL);
    } else if (statePtr->format & TYPE_HMAC) {
	statePtr->hctx = HMAC_CTX_new();
	res = (statePtr->hctx != NULL);
    } else if (statePtr->format & TYPE_CMAC) {
	statePtr->cctx = CMAC_CTX_new();
	res = (statePtr->cctx != NULL);
    }
    if (!res) {
	Tcl_AppendResult(interp, "Create context failed: ", REASON(), NULL);
	return TCL_ERROR;
    }

    /* Initialize hash function */
    if (statePtr->format & TYPE_MD) {
	res = EVP_DigestInit_ex(statePtr->ctx, md, NULL);
    } else if (statePtr->format & TYPE_HMAC) {
	key = Tcl_GetByteArrayFromObj(keyObj, &key_len);
	res = HMAC_Init_ex(statePtr->hctx, (const void *) key, key_len, md, NULL);
    } else if (statePtr->format & TYPE_CMAC) {
	key = Tcl_GetByteArrayFromObj(keyObj, &key_len);
	res = CMAC_Init(statePtr->cctx, (const void *) key, key_len, cipher, NULL);
    }
    if (!res) {
	Tcl_AppendResult(interp, "Initialize failed: ", REASON(), NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------
 *
 * Tls_DigestUpdate --
 *
 *	Update a hash function
 *
 * Returns:
 *	1 if successful or 0 for failure
 *
 * Side effects:
 *	Adds buf to hash function
 *
 *-------------------------------------------------------------------
 */
int Tls_DigestUpdate(DigestState *statePtr, char *buf, size_t read, int show) {
    int res = 0;

    if (statePtr->format & TYPE_MD) {
	res = EVP_DigestUpdate(statePtr->ctx, buf, read);
    } else if (statePtr->format & TYPE_HMAC) {
	res = HMAC_Update(statePtr->hctx, buf, read);
    } else if (statePtr->format & TYPE_CMAC) {
	res = CMAC_Update(statePtr->cctx, buf, read);
    }
    if (!res && show) {
	Tcl_AppendResult(statePtr->interp, "Update failed: ", REASON(), NULL);
	return TCL_ERROR;
    }
    return res;
}

/*
 *-------------------------------------------------------------------
 *
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
	res = HMAC_Final(statePtr->hctx, md_buf, &md_len);
    } else if (statePtr->format & TYPE_CMAC) {
	size_t len;
	res = CMAC_Final(statePtr->cctx, md_buf, &len);
	md_len = (unsigned int) len;
    }
    if (!res) {
	Tcl_AppendResult(interp, "Finalize digest failed: ", REASON(), NULL);
	return TCL_ERROR;
    }

    /* Return message digest as either a binary or hex string */
    if (statePtr->format & BIN_FORMAT) {
	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(md_buf, md_len));








|







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
	res = HMAC_Final(statePtr->hctx, md_buf, &md_len);
    } else if (statePtr->format & TYPE_CMAC) {
	size_t len;
	res = CMAC_Final(statePtr->cctx, md_buf, &len);
	md_len = (unsigned int) len;
    }
    if (!res) {
	Tcl_AppendResult(interp, "Finalize failed: ", REASON(), NULL);
	return TCL_ERROR;
    }

    /* Return message digest as either a binary or hex string */
    if (statePtr->format & BIN_FORMAT) {
	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(md_buf, md_len));

289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    if ((res = Tcl_SetChannelOption(interp, chan, "-translation", "binary")) == TCL_ERROR) {
	goto done;
    }
    Tcl_SetChannelBufferSize(chan, BUFFER_SIZE);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {

	res = TCL_ERROR;
	goto done;
    }

    /* Initialize hash function */
    if ((res = Tls_DigestInit(interp, statePtr, md, cipher, keyObj)) != TCL_OK) {
	goto done;
    }

    /* Read file data and update hash function */
    while (!Tcl_Eof(chan)) {
	len = Tcl_ReadRaw(chan, (char *) buf, BUFFER_SIZE);
	if (len > 0) {
	    if (!Tls_DigestUpdate(statePtr, &buf[0], (size_t) len)) {
		Tcl_AppendResult(interp, "Update digest failed: ", REASON(), NULL);
		res = TCL_ERROR;
		goto done;
	    }
	}
    }

    /* Finalize hash function and calculate message digest */







>













|
<







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
    if ((res = Tcl_SetChannelOption(interp, chan, "-translation", "binary")) == TCL_ERROR) {
	goto done;
    }
    Tcl_SetChannelBufferSize(chan, BUFFER_SIZE);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
	res = TCL_ERROR;
	goto done;
    }

    /* Initialize hash function */
    if ((res = Tls_DigestInit(interp, statePtr, md, cipher, keyObj)) != TCL_OK) {
	goto done;
    }

    /* Read file data and update hash function */
    while (!Tcl_Eof(chan)) {
	len = Tcl_ReadRaw(chan, (char *) buf, BUFFER_SIZE);
	if (len > 0) {
	    if (!Tls_DigestUpdate(statePtr, &buf[0], (size_t) len, 1)) {

		res = TCL_ERROR;
		goto done;
	    }
	}
    }

    /* Finalize hash function and calculate message digest */
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446

    /* Get bytes from underlying channel */
    parent = Tcl_GetStackedChannel(statePtr->self);
    read = Tcl_ReadRaw(parent, buf, toRead);

    /* Update hash function */
    if (read > 0) {
	if (!Tls_DigestUpdate(statePtr, buf, (size_t) read)) {
	    Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Digest update failed: %s", REASON()));
	    *errorCodePtr = EINVAL;
	    return -1;
	}
	/* This is correct */
	read = -1;
	*errorCodePtr = EAGAIN;
	    







|
|







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

    /* Get bytes from underlying channel */
    parent = Tcl_GetStackedChannel(statePtr->self);
    read = Tcl_ReadRaw(parent, buf, toRead);

    /* Update hash function */
    if (read > 0) {
	if (!Tls_DigestUpdate(statePtr, buf, (size_t) read, 0)) {
	    Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Update failed: %s", REASON()));
	    *errorCodePtr = EINVAL;
	    return -1;
	}
	/* This is correct */
	read = -1;
	*errorCodePtr = EAGAIN;
	    
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	    res = HMAC_Final(statePtr->hctx, md_buf, &md_len);
	} else if (statePtr->format & TYPE_CMAC) {
	    size_t len;
	    res = CMAC_Final(statePtr->cctx, md_buf, &len);
	    md_len = (unsigned int) len;
	}
	if (!res) {
	    Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Digest finalize failed: %s", REASON()));
	    *errorCodePtr = EINVAL;

	/* Write message digest to output channel as byte array or hex string */
	} else if (md_len > 0) {
	    if ((statePtr->format & BIN_FORMAT) && toRead >= (int) md_len) {
		read = md_len;
		memcpy(buf, md_buf, read);







|







464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
	    res = HMAC_Final(statePtr->hctx, md_buf, &md_len);
	} else if (statePtr->format & TYPE_CMAC) {
	    size_t len;
	    res = CMAC_Final(statePtr->cctx, md_buf, &len);
	    md_len = (unsigned int) len;
	}
	if (!res) {
	    Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Finalize failed: %s", REASON()));
	    *errorCodePtr = EINVAL;

	/* Write message digest to output channel as byte array or hex string */
	} else if (md_len > 0) {
	    if ((statePtr->format & BIN_FORMAT) && toRead >= (int) md_len) {
		read = md_len;
		memcpy(buf, md_buf, read);
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

    /* Abort if nothing to process */
    if (toWrite <= 0 || statePtr->self == (Tcl_Channel) NULL) {
	return 0;
    }

    /* Update hash function */
    if (toWrite > 0 && !Tls_DigestUpdate(statePtr, buf, (size_t) toWrite)) {
	Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Digest update failed: %s", REASON()));
	*errorCodePtr = EINVAL;
	return -1;
    }
    return toWrite;
}

/*







|
|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531

    /* Abort if nothing to process */
    if (toWrite <= 0 || statePtr->self == (Tcl_Channel) NULL) {
	return 0;
    }

    /* Update hash function */
    if (toWrite > 0 && !Tls_DigestUpdate(statePtr, buf, (size_t) toWrite, 0)) {
	Tcl_SetChannelError(statePtr->self, Tcl_ObjPrintf("Update failed: %s", REASON()));
	*errorCodePtr = EINVAL;
	return -1;
    }
    return toWrite;
}

/*
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
    }

    /* Make sure to operate on the topmost channel */
    chan = Tcl_GetTopChannel(chan);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	Tcl_AppendResult(interp, "Initialize digest error: memory allocation failure", (char *) NULL);
	return TCL_ERROR;
    }
    statePtr->self = chan;
    statePtr->mode = mode;

    /* Initialize hash function */
    if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK) {







|







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
    }

    /* Make sure to operate on the topmost channel */
    chan = Tcl_GetTopChannel(chan);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
	return TCL_ERROR;
    }
    statePtr->self = chan;
    statePtr->mode = mode;

    /* Initialize hash function */
    if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK) {
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	    buf = Tcl_GetByteArrayFromObj(objv[2], &len);
	} else {
	    Tcl_WrongNumArgs(interp, 1, objv, "update data");
	    return TCL_ERROR;
	}

	/* Update hash function */
	if (!Tls_DigestUpdate(statePtr, buf, (size_t) len)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("Digest update failed: %s", REASON()));
	    return TCL_ERROR;
	}

    } else {
	/* Finalize hash function and calculate message digest */
	if (Tls_DigestFinialize(interp, statePtr) != TCL_OK) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("Digest finalize failed: %s", REASON()));
	    return TCL_ERROR;
	}

	Tcl_DeleteCommandFromToken(interp, statePtr->token);
    }
    return TCL_OK;
}







|
<






<







926
927
928
929
930
931
932
933

934
935
936
937
938
939

940
941
942
943
944
945
946
	    buf = Tcl_GetByteArrayFromObj(objv[2], &len);
	} else {
	    Tcl_WrongNumArgs(interp, 1, objv, "update data");
	    return TCL_ERROR;
	}

	/* Update hash function */
	if (!Tls_DigestUpdate(statePtr, buf, (size_t) len, 1)) {

	    return TCL_ERROR;
	}

    } else {
	/* Finalize hash function and calculate message digest */
	if (Tls_DigestFinialize(interp, statePtr) != TCL_OK) {

	    return TCL_ERROR;
	}

	Tcl_DeleteCommandFromToken(interp, statePtr->token);
    }
    return TCL_OK;
}
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
int Tls_DigestInstance(Tcl_Interp *interp, Tcl_Obj *cmdObj, const EVP_MD *md,
	const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj) {
    DigestState *statePtr;
    char *cmdName = Tcl_GetStringFromObj(cmdObj, NULL);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	Tcl_AppendResult(interp, "Initialize digest error: memory allocation failure", (char *) NULL);
	return TCL_ERROR;
    }

    /* Initialize hash function */
    if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK) {
	return TCL_ERROR;
    }







|







985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
int Tls_DigestInstance(Tcl_Interp *interp, Tcl_Obj *cmdObj, const EVP_MD *md,
	const EVP_CIPHER *cipher, int format, Tcl_Obj *keyObj) {
    DigestState *statePtr;
    char *cmdName = Tcl_GetStringFromObj(cmdObj, NULL);

    /* Create state data struct */
    if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
	return TCL_ERROR;
    }

    /* Initialize hash function */
    if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK) {
	return TCL_ERROR;
    }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
	DigestState *statePtr;

	if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	    Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
	    return TCL_ERROR;
	}
	if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK ||
	    Tls_DigestUpdate(statePtr, data, (size_t) len) == 0 ||
	    Tls_DigestFinialize(interp, statePtr) != TCL_OK) {
	    Tls_DigestFree(statePtr);
	    return TCL_ERROR;
	}
	Tls_DigestFree(statePtr);
	return TCL_OK;
    }







|







1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
	DigestState *statePtr;

	if ((statePtr = Tls_DigestNew(interp, format)) == NULL) {
	    Tcl_AppendResult(interp, "Memory allocation error", (char *) NULL);
	    return TCL_ERROR;
	}
	if (Tls_DigestInit(interp, statePtr, md, cipher, keyObj) != TCL_OK ||
	    Tls_DigestUpdate(statePtr, data, (size_t) len, 1) == 0 ||
	    Tls_DigestFinialize(interp, statePtr) != TCL_OK) {
	    Tls_DigestFree(statePtr);
	    return TCL_ERROR;
	}
	Tls_DigestFree(statePtr);
	return TCL_OK;
    }