| 265 | } |
| 266 | |
| 267 | void MD5_Final(unsigned char *result, MD5_CTX *ctx) |
| 268 | { |
| 269 | unsigned long used, free; |
| 270 | |
| 271 | used = ctx->lo & 0x3f; |
| 272 | |
| 273 | ctx->buffer[used++] = 0x80; |
| 274 | |
| 275 | free = 64 - used; |
| 276 | |
| 277 | if (free < 8) { |
| 278 | memset(&ctx->buffer[used], 0, free); |
| 279 | body(ctx, ctx->buffer, 64); |
| 280 | used = 0; |
| 281 | free = 64; |
| 282 | } |
| 283 | |
| 284 | memset(&ctx->buffer[used], 0, free - 8); |
| 285 | |
| 286 | ctx->lo <<= 3; |
| 287 | ctx->buffer[56] = ctx->lo & 0xFF; |
| 288 | ctx->buffer[57] = (ctx->lo >> 8) & 0xFF; |
| 289 | ctx->buffer[58] = (ctx->lo >> 16) & 0xFF; |
| 290 | ctx->buffer[59] = (ctx->lo >> 24) & 0xFF; |
| 291 | ctx->buffer[60] = ctx->hi & 0xFF; |
| 292 | ctx->buffer[61] = (ctx->hi >> 8) & 0xFF; |
| 293 | ctx->buffer[62] = (ctx->hi >> 16) & 0xFF; |
| 294 | ctx->buffer[63] = (ctx->hi >> 24) & 0xFF; |
| 295 | |
| 296 | body(ctx, ctx->buffer, 64); |
| 297 | |
| 298 | result[0] = ctx->a & 0xFF; |
| 299 | result[1] = (ctx->a >> 8) & 0xFF; |
| 300 | result[2] = (ctx->a >> 16) & 0xFF; |
| 301 | result[3] = (ctx->a >> 24) & 0xFF; |
| 302 | result[4] = ctx->b & 0xFF; |
| 303 | result[5] = (ctx->b >> 8) & 0xFF; |
| 304 | result[6] = (ctx->b >> 16) & 0xFF; |
| 305 | result[7] = (ctx->b >> 24) & 0xFF; |
| 306 | result[8] = ctx->c & 0xFF; |
| 307 | result[9] = (ctx->c >> 8) & 0xFF; |
| 308 | result[10] = (ctx->c >> 16) & 0xFF; |
| 309 | result[11] = (ctx->c >> 24) & 0xFF; |
| 310 | result[12] = ctx->d & 0xFF; |
| 311 | result[13] = (ctx->d >> 8) & 0xFF; |
| 312 | result[14] = (ctx->d >> 16) & 0xFF; |
| 313 | result[15] = (ctx->d >> 24) & 0xFF; |
| 314 | |
| 315 | memset(ctx, 0, sizeof(*ctx)); |
| 316 | } |
| 317 | |
| 318 | } // anonymous namespace |
| 319 | |