@@ -232,23 +232,49 @@ void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size
232
232
233
233
void crypto_sha_update_nobuf (crypto_sha_context * ctx , const unsigned char * input , size_t ilen , int islast )
234
234
{
235
- unsigned char * in_pos = input ;
235
+ // Accept only:
236
+ // 1. Last block which may be incomplete
237
+ // 2. Non-last block which is complete
238
+ MBED_ASSERT (islast || ilen == ctx -> blocksize );
239
+
240
+ const unsigned char * in_pos = input ;
236
241
int rmn = ilen ;
237
242
uint32_t sha_ctl_start = (CRPT -> SHA_CTL & ~(CRPT_SHA_CTL_DMALAST_Msk | CRPT_SHA_CTL_DMAEN_Msk )) | CRPT_SHA_CTL_START_Msk ;
243
+ uint32_t sha_opmode = (CRPT -> SHA_CTL & CRPT_SHA_CTL_OPMODE_Msk ) >> CRPT_SHA_CTL_OPMODE_Pos ;
244
+ uint32_t DGST0_old , DGST1_old , DGST2_old , DGST3_old , DGST4_old , DGST5_old , DGST6_old , DGST7_old ;
238
245
239
246
while (rmn > 0 ) {
240
247
CRPT -> SHA_CTL = sha_ctl_start ;
241
248
242
249
uint32_t data = nu_get32_be (in_pos );
243
- if (islast && rmn <= 4 ) {
244
- uint32_t lastblock_size = ctx -> total & ctx -> blocksize_mask ;
245
- if (lastblock_size == 0 ) {
246
- lastblock_size = ctx -> blocksize ;
250
+ if (rmn <= 4 ) { // Last word of a (in)complete block
251
+ if (islast ) {
252
+ uint32_t lastblock_size = ctx -> total & ctx -> blocksize_mask ;
253
+ if (lastblock_size == 0 ) {
254
+ lastblock_size = ctx -> blocksize ;
255
+ }
256
+ CRPT -> SHA_DMACNT = lastblock_size ;
257
+ CRPT -> SHA_CTL = sha_ctl_start | CRPT_SHA_CTL_DMALAST_Msk ;
258
+ }
259
+ else {
260
+ switch (sha_opmode ) {
261
+ case SHA_MODE_SHA256 :
262
+ DGST7_old = CRPT -> SHA_DGST7 ;
263
+ case SHA_MODE_SHA224 :
264
+ DGST5_old = CRPT -> SHA_DGST5 ;
265
+ DGST6_old = CRPT -> SHA_DGST6 ;
266
+ case SHA_MODE_SHA1 :
267
+ DGST0_old = CRPT -> SHA_DGST0 ;
268
+ DGST1_old = CRPT -> SHA_DGST1 ;
269
+ DGST2_old = CRPT -> SHA_DGST2 ;
270
+ DGST3_old = CRPT -> SHA_DGST3 ;
271
+ DGST4_old = CRPT -> SHA_DGST4 ;
272
+ }
273
+
274
+ CRPT -> SHA_CTL = sha_ctl_start ;
247
275
}
248
- CRPT -> SHA_DMACNT = lastblock_size ;
249
- CRPT -> SHA_CTL = sha_ctl_start | CRPT_SHA_CTL_DMALAST_Msk ;
250
276
}
251
- else {
277
+ else { // Non-last word of a complete block
252
278
CRPT -> SHA_CTL = sha_ctl_start ;
253
279
}
254
280
while (! (CRPT -> SHA_STS & CRPT_SHA_STS_DATINREQ_Msk ));
@@ -258,9 +284,34 @@ void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input
258
284
rmn -= 4 ;
259
285
}
260
286
261
- if (islast ) {
287
+ if (islast ) { // Finish of last block
262
288
while (CRPT -> SHA_STS & CRPT_SHA_STS_BUSY_Msk );
263
289
}
290
+ else { // Finish of non-last block
291
+ // No H/W flag to indicate finish of non-last block process.
292
+ // Values of SHA_DGSTx registers will change as last word of the block is input, so use it for judgement.
293
+ int isfinish = 0 ;
294
+ while (! isfinish ) {
295
+ switch (sha_opmode ) {
296
+ case SHA_MODE_SHA256 :
297
+ if (DGST7_old != CRPT -> SHA_DGST7 ) {
298
+ isfinish = 1 ;
299
+ break ;
300
+ }
301
+ case SHA_MODE_SHA224 :
302
+ if (DGST5_old != CRPT -> SHA_DGST5 || DGST6_old != CRPT -> SHA_DGST6 ) {
303
+ isfinish = 1 ;
304
+ break ;
305
+ }
306
+ case SHA_MODE_SHA1 :
307
+ if (DGST0_old != CRPT -> SHA_DGST0 || DGST1_old != CRPT -> SHA_DGST1 || DGST2_old != CRPT -> SHA_DGST2 ||
308
+ DGST3_old != CRPT -> SHA_DGST3 || DGST4_old != CRPT -> SHA_DGST4 ) {
309
+ isfinish = 1 ;
310
+ break ;
311
+ }
312
+ }
313
+ }
314
+ }
264
315
}
265
316
266
317
void crypto_sha_getinternstate (unsigned char output [], size_t olen )
0 commit comments